未捕获(承诺)错误

时间:2018-05-22 18:29:54

标签: javascript es6-promise

这显然是一个SSCCE。我有以下(jsFiddle here):

<html>
  <body>
    <input id='file-dlg' type='file'/>
    <br/>
    <button id='submit' type='button'>submit</button>
    <script>
     document.getElementById('file-dlg').addEventListener('change', storeAPromise);
     var p; 
     function storeAPromise() {
       p = new Promise(function executor(resolve, reject) {
         try {
           throw new Error('snafu');
         } catch(e) {
           reject(e);
         }
       });
     };
     document.getElementById('submit').onclick = function() {
       p.then(function() {}, function reject(e) {
         console.error('some problem happenned', e);
       });
     };
    </script>
  </body>
</html>

当用户使用文件对话框选择文件时,我希望在控制台上打印任何内容,因为Error被捕获并且承诺的reject功能是调用。相反,我希望错误出现在控制台上,并带有描述&#34;发生了一些错误&#34;只有当我点击&#34;提交&#34;按钮。

然而,这不是我观察到的。一旦用户选择了我在控制台上看到的对话框的文件:

Uncaught (in promise) Error: snafu(…)

当用户按下&#34;提交&#34;按钮我确实看到了预期的日志行&#34;发生了一些问题&#34;但是我不明白为什么我也看到了早期的&#34; Uncaught(in promise)&#34;用户使用文件对话框选择文件时的日志行。我也不明白为什么错误被描述为&#34; Uncaught&#34;鉴于我(无条件地)捕获所有异常并且简单地调用reject函数。

1 个答案:

答案 0 :(得分:6)

它不是未被捕获的例外,它是未被捕获的拒绝。承诺不应该在被拒绝状态下悬挂而没有附加错误回调 - 这就是控制台警告你的原因。您还可以使用unhandledrejection event在您的应用程序中处理这些案例。

如果您想稍后处理错误(在用户单击按钮时安装处理程序,可能永远不会!),您仍需要立即安装空回调(明确忽略错误)以禁止警告

var p = Promise.resolve();
document.getElementById('file-dlg').addEventListener('change', function createPromise() {
  p = new Promise(function executor(resolve, reject) {
    throw new Error('snafu');
  });
  p.catch(e => {/* ignore for now */});
});
document.getElementById('submit').addEventListener('click', function addErrorHandler() {
  p.catch(function onReject(e) {
    console.error('some problem happened', e);
  });
});

请注意,您不需要try / catch - 承诺构造函数默认情况下会捕获执行程序中的所有异常。