Javascript异常隐藏在Promises中.如何显示它们而不被抓住? [英] Javascript Exceptions are hidden in Promises. How can I display them without catch?

查看:109
本文介绍了Javascript异常隐藏在Promises中.如何显示它们而不被抓住?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如出色(已接受)的答案所指出的那样,承诺不会隐藏异常.我想详细说明如何看不见Promise中的异常:

Promises do not hide exceptions, as was pointed out by the excellent (accepted) answer. I want to elaborate on how exceptions in promises were invisible:

我正在开发一个使用专有库进行ajax调用的项目.现在,如果ajax调用的回调出现问题,则将引发异常.然后,此异常将触发调用reject(),然后将其静默丢弃.实际上,这些异常不是隐藏的,而是在空的错误回调中积极地处理了进一步的代码.最终导致了一种情况,甚至很难意识到已经发生了错误.

I was working on a project that used a propriatary library to make ajax calls. Now in case something in the callback of the ajax-call went wrong an exception would be thrown. This exception would then trigger the reject() to be called, which was then silently discarded. In fact the exceptions were not hidden, but actively disposed of further down the code in an empty error-callback. This ultimatly led to a situation where it was very difficult to even recognize that an error had occured.

这里是原始问题:

我知道我可以在所有Promise中添加一个catch块,并在console.log中记录错误.在我的用例中,我需要在调用堆栈的更高级别捕获异常.

I know that I can add a catch-block to all my promises and console.log the error there. In my usecase I need to catch the exceptions at a higher level up the call-stack.

http://jamesknelson.com/are-es6-promises-吞下你的错误/

关于SO的另一个问题,被接受的答案还提出了catch-blocks:

Here in another question on SO, the accepted answer also proposes catch-blocks:

在JavaScript的Promises中捕获Promises中生成的错误

推荐答案

JavaScript默默地吞没了Promise中引发的异常.

Javascript silently swallows Exceptions that are thrown within a Promise.

不,不是.在promise执行器(您通过new Promise传递的函数)或then/catch处理程序中引发的异常用作对promise的拒绝值.如果您有未处理的拒绝,任何体面的实现也会记录控制台错误.例如,在最新版本的Chrome或Firefox中尝试以下操作:

No, it doesn't. An exception thrown in a promise executor (the function you pass new Promise) or a then/catch handler is used as the value of the rejection of the promise. Any decent implementation will also log a console error if you have unhandled rejections. For instance, try this in a recent version of Chrome or Firefox:

new Promise(() => { throw new Error("Unhandled"); })

在控制台中,您将找到:

In the console you'll find:


Uncaught (in promise) Error: Unhandled
    at Promise (js:13)
    at new Promise ()
    at js:13

很快,NodeJS将开始处理未处理的拒绝,就像处理未处理的异常一样.因为拒绝例外.

Soon, NodeJS will start terminating the process on unhandled rejections just like unhandled exceptions. Because rejections are exceptions.

我不想在我所有的承诺中都加入一个障碍.

I do not want to add a catch-block to all my promises.

您不必这样做.诺言的规则是您返还诺言或处理对诺言的拒绝;几乎从来没有. (您只会做很少的事,例如,当您包装"使它变得更高级的错误时.)因此,您只需要catch即可保证不会传播给调用者. .最佳实践是传播到您可以达到的最高水平,然后在那里进行处理.大多数情况下,您不会写catch,因为您在传播承诺.

You don't have to. The rule of promises is you either return the promise or handle rejections from it; almost never both. (You'd do both only rarely, such as when you're "wrapping" the error that occurred to make it more high-level.) So you only need a catch on promises that you don't propagate to the caller. Best practice is to propagate to the highest level you can and then handle them there. Most of the time you don't write a catch because you're propagating the promise.

我可以猴子式(或其他方式)修补本地Promises,使它们不再隐藏我的异常吗?

Can I monkey-patch (or else) the native Promises in such a way that they stop hiding my exceptions?

再说一次,他们没有.您可以替换PromisePromise.prototype.then,以便它们向控制台报告异常,但是最终您将报告由后续处理程序进行处理且不应该报告的事物.例如:

Well, again, they don't. You can replace Promise and Promise.prototype.then so they report exceptions to the console, but you'll end up reporting things that are handled by subsequent handlers and shouldn't be reported. For example:

// NOT RECOMMENDED
const RealPromise = Promise;
Promise = class Promise extends RealPromise {
  constructor(executor) {
    super((resolve, reject) => {
      try {
        executor(resolve, reject);
      } catch (e) {
        console.error(e);
        reject(e);
      }
    });
  }
  
  then(onResolved, onRejected) {
    return super.then(val => {
      try {
        return onResolved(val);
      } catch (e) {
        console.error(e);
        throw e;
      }
    }, onRejected);
  }
};

new Promise(() => {
  throw new Error("Handled");
}).catch(e => {
  console.log("But I handled it!");
});

...但是,正如您所看到的,这不是一个好主意.

...but it wouldn't be a good idea, as you can see.

如果您遵循传播或处理"规则,则可以使用内置的Promise.

If you follow the propagate-or-handle rule, you should be fine with built-in promises.

也许还应该注意async/await语法,它们是ES2017的新语法:使用async/await时,promise拒绝值用作异常,从而闭合圆圈:

It's also probably worth noting async/await syntax, which are new as of ES2017: When using async/await, promise rejection values are used as exceptions, closing the circle:

function foo() {
  return new Promise((resolve, reject) => {
    setTimeout(reject, 500, "Failed");
  });
}
(async () => {
  try {
    await foo();
  } catch (e) {
    console.log("Got error: ", e);
  }
})();

这篇关于Javascript异常隐藏在Promises中.如何显示它们而不被抓住?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆