2013-04-17 43 views
0

我试图修复一些第三方NodeJS(hubot脚本,如果有人关心)。这里的想法是,我们为从前一个调用返回的每个构建提供一次与Teamcity REST API的联系,并遍历它们,打印一条消息。是否有可能阻止节点JS中的父线程?

mapBuildTypeIdToName = (msg, id, callback) -> 
    url = "http://#{hostname}/httpAuth/app/rest/buildTypes/id:#{id}" 
    msg.http(url) 
     .headers(getAuthHeader()) 
     .get() (err, res, body) -> 
     err = body unless res.statusCode = 200 
     buildName = JSON.parse(body).name unless err 
     callback err, msg, buildName 

createAndPublishBuildMap = (builds, msg) -> 

    for build in builds 
     console.log "foo" 
     console.log build 
     mapBuildTypeIdToName msg, build['buildTypeId'], (err, msg, name)-> 
     console.log "bar" 
     console.log build 
     baseMessage = "##{build.number} of #{name} #{build.webUrl}" 
     if build.running 
      status = if build.status == "SUCCESS" then "**Winning**" else "__FAILING__" 
      message = "#{status} #{build.percentageComplete}% Complete :: #{baseMessage}" 
     else 
      status = if build.status == "SUCCESS" then "OK!" else "__FAILED__" 
      message = "#{status} :: #{baseMessage}" 
     msg.send message 

问题如下:在for循环开始时,build有多个对象。这些被迭代,然后输入回调,从而打印出最后的构建builds.length时间。

服务器日志看起来像这样:

 foo 
    build1 
    foo 
    build2 
    bar 
    build2 
    bar 
    build2 

虽然预期/所需的行为是:

foo 
    build1 
    bar 
    build1 
    foo 
    build2 
    bar 
    build2 

所以我有两个问题:

1)为什么这种行为发生?我明白Node JS的非阻塞性质导致主线程(for循环)执行速度快于非阻塞子线程(mapBuildTypeIdToName)。为什么它不会用正确的值调用嵌套函数?为什么只有最后一个值才被调用?

2)我该如何解决这个问题?我如何阻止父线程并等待回调,否则,在Node JS中对于这种性质的问题(有效地是事件驱动的繁忙循环)的规范方法是什么?

+0

你不应该试图阻止maain线程。 Node.js与线程无关。应用程序在单个线程上运行,并使用基于事件循环的体系结构。 – Venemo

回答

1

我假设build是一个字符串。如果是这样,它将是您期望在mapBuildTypeIdToName中的值,因为它是一个基元,并且它们是按值传递的。

但是,在您的回调中,您引用了在循环外部声明的构建变量,因此它的状态将是调用回调时变量所处的状态。在你的情况下,回调在循环完成后被调用,所以它是build2。

要获得您正在查找的结果,请查看异步库中的eachSeries API。它将允许您在数组上运行一系列异步API调用,就好像它们是同步的,而不会实际阻止该线程。

+0

构建是一个对象,像这样: {ID:899, 号码: '181', 运行:真实, percentageComplete:49, 状态: '失败', buildTypeId: 'bt72', 开始日期:' 20130416T235456-0700', href:'/ httpAuth/app/rest/builds/id:899', webUrl:'sanitized'} –

+0

只要你不在其他地方修改对象,它应该仍然可以像我描述的那样工作。但是,如果有一些其他循环执行下列操作,则会出现计时问题。 'build for builds build.id = x' –

相关问题