为什么使用.then()的速度快3倍,然后等待测试?

时间:2018-06-29 00:12:41

标签: javascript

这可能完全是我误解了Java中async / await的工作方式,但是我还没有弄清楚。

我有一个简单的测试,该测试在实际运行测试之前使用一些帮助程序来生成模拟数据。

以下是辅助功能:

async create(numCustomers, businessId, options) {

    options = _.assign({ type: 'customer' }, options);

    const customers = await Factory.createMany('user', options, numCustomers);

    return Promise.all(customers.map(async (c) => {
        await AccountHelper.create(businessId, c.get('id'));
        return c;
    }));
}

这是测试的两个版本:

async/await版本:

const customers = await CustomerHelper.create(10, Constants.fakeBusinessId);

await Promise.all(customers.map(async (c) => {
    await PetHelper.create(1, c.get('id'));
}));

const res = await server.inject(request);
expect(res.statusCode).to.equal(200);

.then()版本:

CustomerHelper.create(10, Constants.fakeBusinessId).then(async (customers) => {

    await Promise.all(customers.map(async (c) => {
        await PetHelper.create(1, c.get('id'));
    }));

    const res = await server.inject(request);
    expect(res.statusCode).to.equal(200);
});

.then()版本在大约2秒内完成,而async/await版本在大约7秒内完成。在这两种形式之间进行更改似乎是唯一的变量。

我正在OSX上运行Node 8.9.4。

我感谢任何见识或教育:)

1 个答案:

答案 0 :(得分:2)

这两种方法的持续时间应大致相同,只要您正确地向测试框架发出测试已完成的信号。 (在大多数测试框架中,通过返回Promise或调用done回调)

如果您没有正确地向框架发出信号,则在异步处理完成(在许多情况下甚至开始)之前,测试将退出。同样,如果您的断言/期望等待异步事件,那么它们甚至不会被创建,并且没有断言的测试(在大多数框架中)是通过测试。因此,async / await成为测试的首选样式,因为更难(尽管并非不可能)错误地向测试框架发出信号(如您的示例所示)。

用正确的方式向测试框架发出信号,表明测试已完成(对于mocha / jest样式框架):

it('does async work with await', async function (){
  let result = await asyncWork()
  assertItWorked(result)
})

it('does async work with returned promise', function (){
  return asyncWork().then(function (result) {
    assertItWorked(result)
  })
})

it('does async work with promise and callback', function (done){
  asyncWork().then(function (result) {
    assertItWorked(result)
    done() // note that this method will timeout if it fails, instead of displaying the error message, but you still get a failure
  })
})

it('does async work with promise and chained callback', function (done){
  asyncWork().then(function (result) {
    assertItWorked(result)
  }).then(done)
})

看起来不正确的不正确方法:

it('does async work but does not wait', function (done){
  asyncWork().then(function (result) {
    assertItWorked(result)
  })
  done() // this gets called before async work is done, and no assertions are made
})

it('does async work with promise and chained callback, but calls callback too soon', function (done){
  asyncWork().then(function (result) {
    assertItWorked(result)
  }).then(done()) // this is effectively identical to the previous example, because done gets called immediately
})

还请注意,async / await样式可以完全捕获asyncWork引发的错误/拒绝,尽管使用更多代码,其他样式也可以。