Node.js 是否可以阻止节点JS中的父线程?
我正在尝试修复一些第三方nodej(如果有人关心的话,请使用hubot脚本)。这里的想法是,对于从上一次调用返回的每个构建,我们都会访问Teamcity REST API一次,并对其进行迭代,打印一条消息Node.js 是否可以阻止节点JS中的父线程?,node.js,coffeescript,hubot,Node.js,Coffeescript,Hubot,我正在尝试修复一些第三方nodej(如果有人关心的话,请使用hubot脚本)。这里的想法是,对于从上一次调用返回的每个构建,我们都会访问Teamcity REST API一次,并对其进行迭代,打印一条消息 mapBuildTypeIdToName = (msg, id, callback) -> url = "http://#{hostname}/httpAuth/app/rest/buildTypes/id:#{id}" msg.http(url) .head
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.length次
服务器日志如下所示:
foo
build1
foo
build2
bar
build2
bar
build2
虽然预期/期望的行为是:
foo
build1
bar
build1
foo
build2
bar
build2
所以我有两个问题:
1) 为什么会发生这种行为?我理解,节点JS的非阻塞性质导致主线程(for循环)的执行速度快于其非阻塞子线程(mapBuildTypeIdToName)。为什么它不仍然使用正确的值调用嵌套函数?为什么只使用最后一个值调用它
2) 我该如何解决这个问题?如何阻止父线程并等待回调,或者,在Node JS中解决此类问题(实际上是事件驱动的忙循环)的规范方法是什么?我假设构建是一个字符串。如果是这样,它将是您在mapBuildTypeIdToName中所期望的值,因为它是一个原语,它们是通过值传递的 然而,在回调内部,您引用的是在循环外部声明的构建变量,因此它的状态将是调用回调时该变量所处的任何状态。在您的例子中,回调在循环完成后被调用,因此它是build2
要获得所需的结果,请查看异步库中的eachSeries API。它将允许您在阵列上运行一系列异步API调用,就像它们是同步的一样,而不会实际阻塞线程。您不应该尝试阻塞maain线程。Node.js与线程无关。应用程序在单个线程上运行,并使用基于事件循环的体系结构。build是这样一个对象:{id:899,数字:'181',running:true,percentageComplete:49,status:'FAILURE',buildTypeId:'bt72',startDate:'20130416T235456-0700',href:'/httpAuth/app/rest/builds/id:899',webUrl:'sanitized'}只要您没有在其他地方修改对象,它应该仍然可以像我描述的那样工作。但是,如果有其他循环执行以下操作,则会出现计时问题<代码>用于内置build.id=x