【问题标题】:Can I prevent that Chrome (v45) pauses on promise rejections?我可以防止 Chrome (v45) 在拒绝承诺时暂停吗?
【发布时间】:2019-07-18 18:47:49
【问题描述】:

如果我在 Chrome 中显示了开发人员工具并且 Promise 被拒绝,则 Chrome 会暂停 javascript 执行并显示消息“Paused on promise denied”。在这种情况下,我能否以某种方式阻止 Chrome 暂停(并且仍然打开 devtools)?

Rejected Promise 是我的应用程序中“正常”流程的一部分,每次在 Chrome 中按下恢复按钮都会很不方便。

您可以通过在 js-console 中输入以下内容在 Chrome 中测试此行为:

new Promise(function(accept, reject) { reject(); }) // (tested in v 45.0.2454.99)

谢谢。

【问题讨论】:

    标签: javascript google-chrome promise es6-promise


    【解决方案1】:

    只有在“源”选项卡中打开“暂停未捕获的异常”时,Chrome 才会执行此操作。

    如果您取消勾选它,它不会因错误而暂停。

    promise 拒绝 在概念上是一个错误。心智建模才是正确的方法,否则以下是无声的错误:

    Promise.resolve().then(function(){
        JSON.prase("{}"); // unhandled rejection, TypeError, typo
        foooooo = 15; // unhandled ReferenceError, undefined
    });
    

    等等。

    如果您想显式抑制拒绝,这类似于同步“捕获所有”,您将执行与同步代码中相同的操作:

    try {
       doSomething();
    } catch(e){
        // explicitly ignore all errors.
    }
    

    承诺:

    doSomething().catch(function(){}); // explicitly don't report rejection
    

    【讨论】:

    • 谢谢,这解决了我的大部分麻烦。但是,如果“异常暂停”处于活动状态,您的“全部捕获”仍会导致 Chrome 暂停。
    • @MikaelSundberg 那么这绝对是一个错误,我会联系 devtools 团队的朋友并对其进行排序。谢谢。
    • @BenjaminGruenbaum:我不认为这是一个错误。调试器也会暂停 throw 异常,无论它们是否被捕获。
    • @Bergi 仅当您勾选了“暂停捕获的异常”时。
    【解决方案2】:

    有趣的是,拒绝一个承诺同步会抛出一个错误,而异步不会。考虑这个例子:

    var willIGetNewPhone = ()=>new Promise(
      (resolve, reject)=>{
        setTimeout(()=>{
          var reason = new Error('mom is not happy');
          reject(reason);
        }, 1000);
      }
    );
    
    willIGetNewPhone()
      .catch(error=>{
        console.log(error.message);
      });
    

    此代码不会引发异常。但是如果 setTimeout 部分被移除,就会抛出异常。

    【讨论】:

    • 同步拒绝一个承诺与异步拒绝它的行为完全相同。您看到的不同之处在于 Chrome 的“未捕获异常暂停”,认为该承诺在被拒绝时没有附加拒绝处理程序。
    【解决方案3】:

    您可以通过异步拒绝来解决此问题(正如@mprcela 所指出的)。这是因为我们可以在实际拒绝执行之前添加catch 处理程序。此外,如果外部 Promise 上有 catch 处理程序,它似乎不会触发暂停。

    但如果没有同步添加catch,它仍然会暂停。

    我通过将拒绝包装在then 块中来延迟执行,这是由于thencatchfinally 处理程序(不是Promise 构造函数)排队并延迟执行(微任务)。

    
    function loadData(url) {
      if (!url) {
        return Promise.resolve().then(() => Promise.reject('no url'));
      }
    
      return fetch(url)
        .then(res => {
          if (!res.ok) {
            // we are already in a then block
            return Promise.reject(res.statusText);
          }
    
          // parse response as json
          return res.json();
        });
    }
    
    loadData()
      .then(() => {
        // ...
      })
      .catch(console.log);
    

    https://javascript.info/microtask-queue

    【讨论】:

    • 无法使用这种方式来处理使用 Promise 同步拒绝的 API。例如:navigator.serviceWorker.register("https://example.com").catch(()=>Promise.resolve())new WritableStream().getWriter().releaseLock().catch(()=>Promise.resolve())
    • @mems 你试过Promise.resolve().then(() => navigator.serviceWorker.register("https://example.com")).catch(console.error); 吗?
    • 如果您启用“暂停异常”+取消选中“捕获异常暂停”(Chrome 77),调试器仍会暂停(“拒绝承诺时暂停”)
    猜你喜欢
    • 2021-07-21
    • 2014-09-21
    • 2018-07-23
    • 2020-06-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多