Angular函数可否部分异步?异步方法抛错及测试捕获失败如何解决
问题解答
1. async 标记的合理性判断
仅为了等待createProduct返回值给整个方法加async是完全合理的,这是async/await语法的标准使用场景,没有任何问题。
你担心的「开头直接throw Error」写法本身没有语法错误,这是JavaScript的规定:async函数内部所有同步抛出的错误,都会被自动封装为rejected状态的Promise返回,不属于错误写法,只是你需要用适配Promise的异常捕获逻辑来处理这个错误,不能用普通同步函数的异常捕获方式。
2. 单元测试报错的原因
你当前用的同步toThrowError断言,只能捕获普通同步函数直接抛出的错误。而doCreateProduct是async函数,不管是开头同步抛错还是await阶段异步抛错,调用后都会返回Promise,错误不会同步抛出到外层,所以会触发未处理的Promise rejection报错。
3. 修复方案
3.1 日常调用时的异常捕获
调用async函数时,必须用异步异常捕获的写法:
// 方案1:await + try/catch (最常用) async function invokeCreate() { try { await service.doCreateProduct() // 后续成功逻辑 } catch (err) { // 捕获所有错误,包括开头同步抛出的Cannot Proceed console.error(err.message) } } // 方案2:用Promise的catch方法 service.doCreateProduct() .then(() => { /* 成功逻辑 */ }) .catch(err => { /* 捕获错误 */ })
3.2 单元测试修正
主流测试框架(Jest、Jasmine等)都支持异步断言,推荐用async/await配合rejects断言的写法:
describe('When cannot proceed', () => { it('should throw error', async () => { // 等待Promise rejected,再断言错误内容 await expect(service.doCreateProduct()).rejects.toThrowError("Cannot Proceed"); }); });
如果习惯用done回调的写法,也可以用如下方式:
describe('When cannot proceed', () => { it('should throw error', (done) => { service.doCreateProduct().catch(err => { expect(err.message).toBe("Cannot Proceed"); done(); }) }); });
内容的提问来源于stack exchange,提问作者avdeveloper
相关产品推荐
相关产品推荐

