[英]Exception gets swallowed in promise chain
I noticed something very strange happening when an exception is thrown inside a chain of promises in Parse for React Native. 当Parse for React Native中的一系列promise中抛出异常时,我注意到发生了一些非常奇怪的事情。 The promise chain never resolves, and never rejects, and the exception is never thrown.
承诺链永远不会解决,永远不会拒绝,并且永远不会抛出异常。 It just disappears silently.
它只是默默地消失。
Here's sample code to recreate the problem: 这是重新创建问题的示例代码:
// Replacing this with Promise.resolve() prints the error.
// Removing this stage prints the error.
Parse.Promise.as()
// Removing this stage causes a red screen error.
.then(function() {
// Replacing this with Parse.Promise.as() causes a red screen error.
return Promise.resolve();
})
.then(function () {
throw new Error("There was a failure");
})
.then(function () { console.log("Success")}, function (err) { console.log(err) });
As you can see from the comments, it only seems to happen in this particular sequence of events. 正如您从评论中看到的那样,它似乎只发生在这个特定的事件序列中。 Removing a stage, or swapping a Parse promise for a native JS promise, causes things to behave again.
删除一个阶段,或者交换一个原生JS承诺的Parse承诺,会导致事情再次发生。 (In my actual code, the "Promise.resolve()" stage is actually a call into a native iOS method that returns a promise.)
(在我的实际代码中,“Promise.resolve()”阶段实际上是对返回promise的本机iOS方法的调用。)
I'm aware that Parse promises don't behave exactly like A+ compliant promises (cf. https://stackoverflow.com/a/31223217/2397068 ). 我知道Parse承诺的行为与A +兼容的承诺完全不同 (参见https://stackoverflow.com/a/31223217/2397068 )。 Indeed, calling
Parse.Promise.enableAPlusCompliant()
before this section of code causes the exception to be caught and printed. 实际上,在此代码段之前调用
Parse.Promise.enableAPlusCompliant()
会导致捕获并打印异常。 But I thought that Parse promises and native JS promises could be used together safely. 但我认为Parse promises和原生JS承诺可以安全地一起使用。
Why is this exception disappearing silently? 为什么这个异常会默默地消失?
Thank you. 谢谢。
For your consideration in addition to technical reasons provided in your quoted answer: 除了引用答案中提供的技术原因外,供您考虑:
ES6/A+ compliant Promise instances share: 符合ES6 / A +标准的Promise实例共享:
then
are executed asynchronously in their own thread after the code which caused them to be executed has run to completion. then
是造成他们要执行已经运行完代码后在自己的线程异步执行。 Irrespective of whether a listener was registered for call back whan a promise becomes settled ( 'fulfilled' or 'rejected'), 无论听众是否注册了回叫,承诺都会得到解决(“履行”或“被拒绝”),
then
registration then
登记 throw
) by a listener is used to reject the promise returned by then
registration, and throw
的值(使用throw
)用于拒绝then
注册返回的promise,和 A promise resolved with a Promise instance synchronizes itself with the eventual settled state and value of the promise provided as argument. 使用Promise实例解析的promise将自身与作为参数提供的最终已解决状态和promise的值同步。 (In the ES6 standard this is described as "locked in").
(在ES6标准中,这被描述为“锁定”)。
Potential characteristics of non compliant promise like objects include 不符合承诺的潜在特征包括对象
then
returned promise after a listener registered in the then call throws an exception. then
返回的promise。 Promise.resolve
can be used to settle its returned promise with a static value, perhaps mainly used in testing. Promise.resolve
可用于通过静态值来解决其返回的promise,可能主要用于测试。 Its chief purpose, however, is to quarantine side effects of non compliant promises. 然而,它的主要目的是隔离不合规承诺的副作用。 A promise returned by
Promise.resolve( thenable)
will exhibit all of behaviours 1-7 above, and none of the non compliant behaviours. Promise.resolve( thenable)
返回的承诺将展示上述1-7的所有行为,并且不会出现任何不符合行为的行为。
IMHO I would suggest only using non A+ promise objects in the environment and in accordance with documentation for the library which created them. 恕我直言我建议只在环境中使用非A + promise对象,并根据创建它们的库的文档。 A non compliant thenable can be used to to resolve an A+ promise directly (which is what Promise.resolve does), but for full predictability of behaviour it should be wrapped in a Promise object using
Promise.resolve( thenable)
before any other use. 非兼容的thenable可用于直接解析A + promise(这是Promise.resolve所做的),但是对于行为的完全可预测性,它应该在任何其他使用之前使用
Promise.resolve( thenable)
包装在Promise对象中。
Note I tried to test Parse promises for A+ compliance but it does not seem to provide a constructor. 注意我试图测试Parse承诺的A +合规性,但它似乎没有提供构造函数。 This makes claims of "almost" or "fully" A+ compliance difficult to quantify.
这使得“几乎”或“完全”A +合规性的主张难以量化。 Thanks to zangw for pointing out the possibility of returning a rejected promise form a listener as an alternative to throwing an exception.
感谢zangw指出可能会将拒绝的promise作为一个侦听器返回,作为抛出异常的替代方法。
Why is this exception disappearing?
为什么这个例外消失了?
Parse does by default not catch exceptions, and promises do swallow them. Parse默认情况下不会捕获异常,并且promises会吞下它们。
Parse is not 100% Promises/A+ compatible, but nonetheless it does try to assimilate thenables that are returned from then
callbacks. 解析是不是100%的承诺/ A +兼容,但尽管如此它试图吸收那些从返回thenables
then
回调。 And it does neither catch exceptions nor executes its own callbacks asynchronously. 并且它既不捕获异常也不异步执行自己的回调。
What you are doing can be reproduced without then
using 你在做什么,不能够被复制
then
使用
var p1 = new Parse.Promise();
var p2 = new Parse.Promise();
// p2 should eventually settle and call these:
p2._resolvedCallbacks = [function (res) { console.log("Success") }];
p2._rejectedCallbacks = [function (err) { console.log(err) }];
function handler() {
throw new Error("There was a failure");
}
// this is what the second `then` call sets up (much simplified):
p1._resolvedCallbacks = [function(result) {
p2.resolve(handler(result)); // throws - oops
}];
// the native promise:
var p = Promise.resolve();
// what happens when a callback result is assimilated:
if (isThenable(p))
p.then(function(result) {
p1.resolve(result);
});
The problem is that p1.resolve
is synchronous, and executes the callbacks on p1
immediately - which in turn does throw. 问题是
p1.resolve
是同步的,并立即在p1
上执行回调 - 这反过来会抛出。 By throwing before p2.resolve
can be called, p2
will stay forever pending. 通过在
p2.resolve
调用之前p2.resolve
, p2
将永远保持未决状态。 The exceptions bubbles up and becomes the completion of p1.resolve()
- which now throws in a callback to a native then
method. 例外冒泡并变成完成
p1.resolve()
-现在抛出在回调于天然then
方法。 The native promise implementation catches the exception and rejects the promise returned by then
with it, which is however ignored everywhere. 本机promise实现捕获异常并拒绝
then
返回的promise,但是无处不在。
silently?
默默?
If your "native" promise implementation supports unhandled rejection warnings, you should be able to see the exception hanging around in the rejected promise. 如果您的“本机”承诺实现支持未处理的拒绝警告,您应该能够在被拒绝的承诺中看到异常。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.