我可以重新抛出一个被拒绝的 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.
}