【问题标题】:Is it possible to block the parent thread in Node JS?是否可以阻止 Node JS 中的父线程?
【发布时间】:2013-04-17 16:49:22
【问题描述】:

我正在尝试修复一些第三方 NodeJS(hubot 脚本,如果有人关心的话)。这里的想法是,对于从先前调用返回的每个构建,我们都会与 Teamcity REST API 联系一次,并对其进行迭代,打印一条消息。

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循环开始时,builds有多个对象。这些被迭代,然后进入回调,从而打印出最后一次构建 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 中这种性质的问题(实际上是事件驱动的繁忙循环)的规范方法是什么?

【问题讨论】:

  • 你不应该试图阻塞主线程。 Node.js 与线程无关。该应用程序在单线程上运行,并使用基于事件循环的架构。

标签: node.js coffeescript hubot


【解决方案1】:

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

然而,在你的回调中,你引用的是在循环外声明的构建变量,所以它的状态将是回调被调用时该变量所处的任何状态。在你的情况下,回调在循环完成后被调用,所以它是 build2。

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

【讨论】:

  • 构建是一个像这样的对象:{ id: 899, number: '181', running: true, percentComplete: 49, status: 'FAILURE', buildTypeId: 'bt72', startDate: '20130416T235456 -0700',href:'/httpAuth/app/rest/builds/id:899',webUrl:'已清理'}
  • 只要您不修改其他地方的对象,它应该仍然像我描述的那样工作。但是,如果有一些其他循环执行以下操作,您将遇到时间问题。 for build in builds build.id = x
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-01-10
  • 1970-01-01
  • 1970-01-01
  • 2019-11-23
  • 2016-09-26
相关资源
最近更新 更多