我可以重新抛出一个被拒绝的 await 函数,并立即捕获它吗
Can I rethrow a rejected await function, and catch it immediately
我想在一个地方捕获所有异常,但我 can't do that currently:
There is an important thing to note if you like more try/catch. The following code won't catch the error:
[...]
Remember: a rejected Promise will propagate up in the stack unless you catch it. To catch the error properly in try/catch you would refactor like so:
whatever().catch(err => console.error(err));
但这是我想要的代码:
async function getMtgJsonVersion() {
try {
const response = await axios(metaUrl).catch((err) => { throw err; });
const { data: { meta: { version } } } = response;
return version;
} catch (error) {
console.error(`Could not fetch MTG JSON metadata: ${error}`);
throw error;
}
}
和我的测试:
// console.error is mocked higher up in the test file
it.only('handles errors in fetching', async () => {
expect.assertions(2);
axios.mockReset(); // I use mockImplementationOnce elsewhere
axios.mockRejectedValueOnce(new Error('bang'));
expect(() => getMtgJsonVersion()).rejects.toThrow('bang');
expect(console.error).toHaveBeenCalledWith(expect.stringContaining('bang'));
});
但是当我 运行 它时,我发现最后的期望没有实现?
expect(jest.fn()).toHaveBeenCalledWith(...expected)
Expected: StringContaining "bang"
Number of calls: 0
我本来希望把我所有的投掷都集中在一个地方,但看起来并没有我想的那么简单。
这可能吗?如何实现?
因为expect(fn).rejects.*
是一个异步动作,所以需要“一点时间”才能完成。
在您的代码中,expect(console.error).toHaveBeenCalledWith(expect.stringContaining('bang'))
将 运行 放在 expect(() => getMtgJsonVersion()).rejects.toThrow('bang');
行之前。那时,console.log
还没有被调用。
要使其按您的预期工作,您必须等到 getMtgJsonVersion
完成,然后对日志函数进行断言。 rejects.toThrow('bang')
return 一个承诺,然后用 await
关键字等待它:
await expect(() => getMtgJsonVersion()).rejects.toThrow('bang');
expect(console.error).toHaveBeenCalledWith(expect.stringContaining('bang'));
我的注意事项:避免在“child”单元中使用try/catch
,只需在“final parent”函数中使用它,如果你只是想在http请求失败时记录:
async function getMtgJsonVersion() {
const { data } = await axios(metaUrl).catch((error) => {
console.error(`Could not fetch MTG JSON metadata: ${error}`);
throw error;
});
return data.meta.version.
}
我想在一个地方捕获所有异常,但我 can't do that currently:
There is an important thing to note if you like more try/catch. The following code won't catch the error:
[...]
Remember: a rejected Promise will propagate up in the stack unless you catch it. To catch the error properly in try/catch you would refactor like so:whatever().catch(err => console.error(err));
但这是我想要的代码:
async function getMtgJsonVersion() {
try {
const response = await axios(metaUrl).catch((err) => { throw err; });
const { data: { meta: { version } } } = response;
return version;
} catch (error) {
console.error(`Could not fetch MTG JSON metadata: ${error}`);
throw error;
}
}
和我的测试:
// console.error is mocked higher up in the test file
it.only('handles errors in fetching', async () => {
expect.assertions(2);
axios.mockReset(); // I use mockImplementationOnce elsewhere
axios.mockRejectedValueOnce(new Error('bang'));
expect(() => getMtgJsonVersion()).rejects.toThrow('bang');
expect(console.error).toHaveBeenCalledWith(expect.stringContaining('bang'));
});
但是当我 运行 它时,我发现最后的期望没有实现?
expect(jest.fn()).toHaveBeenCalledWith(...expected) Expected: StringContaining "bang" Number of calls: 0
我本来希望把我所有的投掷都集中在一个地方,但看起来并没有我想的那么简单。
这可能吗?如何实现?
因为expect(fn).rejects.*
是一个异步动作,所以需要“一点时间”才能完成。
在您的代码中,expect(console.error).toHaveBeenCalledWith(expect.stringContaining('bang'))
将 运行 放在 expect(() => getMtgJsonVersion()).rejects.toThrow('bang');
行之前。那时,console.log
还没有被调用。
要使其按您的预期工作,您必须等到 getMtgJsonVersion
完成,然后对日志函数进行断言。 rejects.toThrow('bang')
return 一个承诺,然后用 await
关键字等待它:
await expect(() => getMtgJsonVersion()).rejects.toThrow('bang');
expect(console.error).toHaveBeenCalledWith(expect.stringContaining('bang'));
我的注意事项:避免在“child”单元中使用try/catch
,只需在“final parent”函数中使用它,如果你只是想在http请求失败时记录:
async function getMtgJsonVersion() {
const { data } = await axios(metaUrl).catch((error) => {
console.error(`Could not fetch MTG JSON metadata: ${error}`);
throw error;
});
return data.meta.version.
}