【问题标题】:What is the proper way to handle asynchronicity in nodeunit?在nodeunit中处理异步的正确方法是什么?
【发布时间】:2011-10-02 01:25:56
【问题描述】:

我是整个堆栈的新手——javascript、node.js、coffeescript、nodeunit。认为我应该一步一步做吗?你可能是对的,但我仍然不会这样做。

这里是测试文件:

testCase = require('nodeunit').testCase

Server = require('./web').WebServer
Client = require('../lib/client').Client
Request = require('../lib/request').Request

OPTIONS = {host: 'localhost', port: 8080, path: '/', method: 'GET'}
SERVER = new Server OPTIONS.port
CLIENT = new Client
REQUEST = new Request OPTIONS
SERVER.start() # asynchronous!

module.exports = testCase
  setUp: (callback) ->
    callback()

  tearDown: (callback) ->
    callback()

  testResponseBodyIsCorrect: (test) ->
    test.expect 1
    process.nextTick ->
      CLIENT.transmit REQUEST #asynchronous!
      process.nextTick ->
        test.equal REQUEST.body, /Ooga/
        test.done()

在内部,它只是 http 库的一个包装器。我正在使用节点 0.4.11。 这实际上不起作用。这里有两个异步调用。如果我在咖啡 REPL 中手动执行此操作,它可以工作——但 nodeunit 比我快得多,所以我遇到了一些事情,为了聪明,我会称之为竞争条件。 咧嘴一笑

这里是“传输”的实现: Http = 需要'http'

exports.Client = class Client

  transmit: (request, callback = null) ->
    req = Http.request request.options, (res) ->
      res.setEncoding 'utf8'
      res.on 'data', (chunk) ->
        request.appendToResponseBody chunk
    req.end()

    console.log "Request sent!"

在运行测试之前,我需要确保服务器已绑定到端口,并且我需要确保“.transmit”在执行断言之前已完成其内部回调以获取响应。

什么是干净的方式(或者至少是有效的方式)来做到这一点?

【问题讨论】:

    标签: node.js coffeescript nodeunit


    【解决方案1】:

    每当您执行异步操作时,您都应该将其余代码放入该异步函数的回调中。所以不是

    CLIENT.transmit 请求 process.nextTick -> ...

    做

    CLIENT.transmit REQUEST,(响应)-> ...

    (我假设您的 CLIENT.transmit 方法以这样一种方式实现,即它使用它得到的响应调用回调——它应该!)

    现在,如果您尝试同时测试客户端和服务器,那么您应该使用EventEmitter——我想您会发现您的SERVER 对象已经是一个,因为它继承自 Node 的 http.Server 类型。由于http.Server 对象在收到请求时会触发request 事件,因此您可以执行以下操作

    SERVER.on 'request', (request) ->
      test.equals REQUEST.body, request.body
    

    很不错,对吧?节点式异步可能令人费解,但它为您提供了一系列惊人的选择。

    【讨论】:

    • 事情开始融合(我喜欢这个词,很少使用它)。我已经编辑了问题以添加“传输”的实现——我相当肯定,这很糟糕。我想我明白了.. 所以“响应”回调是回调,这意味着我应该将它传递进去——传递另一个回调是没有意义的。对吗?
    • 哦!所以这意味着,如果我想构建一个更高的接口,我的客户端或请求包装器/接口最终也应该实现或继承这些事件,而不是依赖于 http 的低级事件。因为 http.request() 的东西发生在客户端内部,事件可能不会神奇地冒泡,对吧?
    • 是的,Node 的好处是没有魔法。一切都在表面上。所以目前,传递给transmit 的callback 参数永远不会被调用。你需要的是res.on 'end', -> callback? res,当它被完全接收到时,它将把响应传递给callback函数(如果存在的话)。
    猜你喜欢
    • 2013-02-22
    • 2012-03-29
    • 1970-01-01
    • 2013-08-31
    • 1970-01-01
    • 1970-01-01
    • 2012-01-18
    • 2018-08-23
    • 2018-05-28
    相关资源
    最近更新 更多