在nodeunit中处理异步性的正确方法是什么?

时间:2011-09-30 22:33:06

标签: node.js coffeescript nodeunit

我是整个堆栈的新品牌 - 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比我快得多,所以我遇到了一些东西,聪明的,我称之为竞争条件。 笑容

以下是'transmit'的实现: Http = require'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”已完成其内部回调以在我执行断言之前获得响应。

这样做的干净方式(或者至少是工作方式)是什么?

1 个答案:

答案 0 :(得分:1)

每当你执行异步操作时,应该将其余代码放在该异步函数的回调中。而不是

CLIENT.transmit REQUEST    process.nextTick - > ...

DO

CLIENT.transmit REQUEST,(回复) - > ...

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

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

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

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