Bluebird,Jasmine和异步函数的未处理拒绝错误

时间:2017-02-27 23:13:26

标签: node.js jasmine bluebird babel

考虑以下(人为的)示例:

import Promise from 'bluebird';

const resolvedPromise = () => {
    return Promise.resolve('Test');
};

const asyncFunc = async (asyncResource) => {
    await resolvedPromise();
    await asyncResource.fetchItem();
};


describe('async/await', () => {
    it('should throw an error', (done) => {
        const mockAsyncResource = jasmine.createSpyObj('mockAsyncResource', ['fetchItem']);

        const mockError = Promise.reject(new Error('HTTP 401 - Access Denied'));

        mockAsyncResource.fetchItem.and.returnValue(mockError);

        return asyncFunc(mockAsyncResource).catch(err => {
            expect(err.message).toEqual('HTTP 401 - Access Denied');
            done();
        });
    });
});

我收到以下输出:

1) async/await
Unhandled rejection Error: HTTP 401 - Access Denied 
... (error stack trace)

✔ should throw an error

规范通过,但Bluebird抱怨未处理的拒绝错误。

由于等待的阻止性质,mockError是否在第二个await有机会调用(并处理)mockError承诺之前报告未处理的拒绝?

处理此方案的最佳方法是什么?我发现promise.suppressUnhandledRejections(),是否就像使用它一样简单?

1 个答案:

答案 0 :(得分:2)

我认为这是混合两种不同类型的承诺所引起的问题。您正在使用bluebird的Promise创建已解决/已拒绝的模拟承诺,但await将返回本机Promise

如果您在Chrome控制台上尝试以下操作,您将看到它仅在使用本机承诺时按预期工作:

let resolvedPromise = () => {
    return Promise.resolve('Test');
};

let asyncFunc = async (asyncResource) => {
    await resolvedPromise();
    await asyncResource.fetchItem();
};

let mockAsyncResource = {fetchItem: () => Promise.reject(new Error("foo"))};

asyncFunc(mockAsyncResource).catch((e) => console.log('handled'))

如果你想坚持创建蓝鸟的承诺,你可能需要用蓝鸟的Promise.try包装你的异步函数,虽然我无法测试这个:

let asyncFunc = async (asyncResource) => {
    return Promise.try(async () => {
        await resolvedPromise();
        await asyncResource.fetchItem();
    });
};