考虑以下(人为的)示例:
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()
,是否就像使用它一样简单?
答案 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();
});
};