Chrome 开发工具在拒绝承诺时暂停,即使我正在捕捉它

Chrome Dev Tools pausing on rejected promise even though I'm catching it

我有以下打字稿代码,其中我从 promise 创建函数中抛出同步错误:

function testExc(url: string): Promise<GLTF | undefined> {
    try {
        const promise: Promise<GLTF> = new Promise((resolve, reject) => {
            throw Error('hi')
        })
        promise.catch((err) => { console.log(`Caught ${err}`) })
        return promise
    } catch (e) {
        return Promise.resolve()
    }
}

令我惊讶的是,在 throw 行的 Chrome 开发工具中触发了 "Paused on promise rejection"。我打开了 "Pause on Exceptions",关闭了 "Pause on caught exceptions",因为我想了解未捕获的异常。

为什么暂停了?我通过两种方式捕获异常:使用 .catch 和围绕整个事物的 try/catch。当我继续时,.catch 节按预期捕获它。

我在 Windows 10 上使用 Chrome 80.0.3987.116,打字稿 3.7。

转译后的 JS 代码如下所示,如果有帮助:

function testExc(url) {
  try {
    const promise = new Promise((resolve, reject) => {
      throw Error('hi');
      resolve(undefined);
    });
    promise.catch(err => {console.log(`Caught ${err}`);});
    return promise;
  }
  catch (e) {
    return Promise.resolve(undefined);
  }
}

issue 是在 2015 年作为铬的错误报告提出的。以下是我在讨论中看到的一些相关说法:

The constructor callback is called synchronously before the ".catch()" code is executed, so at the time when the exception is thrown it is indeed uncaught. Later it becomes caught ... (aandrey@chromium.org)

Try-catch scope is static. At the time of throw, we know that it's going to be caught. (yangguo@chromium.org)

At the point the promise implementation checks and invokes the rejection handler can be a lot later. DevTools semantics require to break at the throw site though, to make any sense of "break on exception". (yangguo@chromium.org)

So I guess the scenario we are discussing is the case where the Promise is rejected in the constructor ... In this case, there is no chance to attach a reject handler yet. (yangguo@chromium.org)

长话短说,当您在 promise 构造函数中抛出错误时,devtools 很难识别它是否已被处理。

相反,在您的构造函数中处理它:

function testExc(url) {
  return new Promise((resolve, reject) => {
    try {
      throw new Error('hi');
    }
    catch (e) {
      console.log(`Caught ${e}`);
      resolve();
    }
  })
}