done() 回调的意义何在?

What is the point of the done() callback?

在 Mochajs 中,他们使用 done() 来测试异步代码,如下所示:

describe('User', function() {
  describe('#save()', function() {
    it('should save without error', function(done) {
      var user = new User('Luna');
      user.save(function(err) {
        if (err) throw err;
        done();
      });
    });
  });
});

这到底是什么意思?我做了 console.log(done.toString()),我得到了这个:

function (err) {
  if (err instanceof Error || toString.call(err) === '[object Error]') {
    return done(err);
  }
  if (err) {
    if (Object.prototype.toString.call(err) === '[object Object]') {
      return done(new Error('done() invoked with non-Error: '
        + JSON.stringify(err)));
    }
    return done(new Error('done() invoked with non-Error: ' + err));
  }
  done();
}

这里最后的done()和第一段代码的done()有区别吗?

由于 node.js 的异步特性,您必须告诉 Mocha 您已完成测试。

对于经典的同步语言,方法完成时您就完成了。但是在节点中,首先执行整个方法,然后在一段时间后执行 user.save().

的内部主体

Mocha 只是等待测试直到 done() 被调用,因为它没有任何其他选项来查找是否应该执行其他操作或完成。

您的输出只是函数体 done

Mocha 能够处理同步和异步测试。当你 运行 同步测试时,你可以将它作为匿名函数传递给 it 而你不需要做任何其他事情:当函数 [=42= 时,Mocha 知道测试已经结束].但是,如果您要运行进行异步测试,则必须告诉 Mocha 测试是异步的。有两种方法可以做到这一点:

  1. 声明你传递给it的匿名函数接受一个参数。 Mocha 将使用单个参数调用您的匿名函数,该参数是您必须调用的函数以指示您的测试已经结束。 (由于传统,此参数称为 done。您可以将其称为 completecbplatypus,它们的作用相同。)如果您调用 done 没有值,测试成功。有一个值,测试失败,该值应该是一个 Error 对象或从 Error.

  2. 派生的对象
  3. Return一个承诺:摩卡会等待承诺被解决或拒绝。如果解决了,则测试成功。如果被拒绝,则测试失败。

您在执行 done.toString() 时看到的代码只是 Mocha 在声明它接受参数时传递给测试的函数的代码。您可以在其中看到我上面提到的一些内容(例如,如果您将参数传递给 done,它应该是 Error 或派生自 Error)。 done 里面还有一个 done 函数,它是 Mocha 私有的。

所有测试用例包括before()after()beforeEach()afterEach()最后必须调用done()告诉Mocha所有任务完成.

如果 done() 缺失,将引发超时异常,因为 Mocha 将等待 done() 直到超时。