我想返回一个$q实例,这样,如果客户端不使用拒绝处理程序调用'then',那么就会运行默认的处理程序。
例如,假设默认为alert(1)
然后mypromise.then(function(result){...})
将提醒1,但mypromise.then(null, function(reason){alert(2)})
将提醒2
让我们假设有一种方法可以做到这一点
因此,我们有一个神奇的机器,它总是可以发现.then
是否用函数的第二个参数来调用特定的promise。
那又怎样
所以你可以检测是否有人这样做:
myPromise.then(..., function(){ F(); });
在任何时间、任何地点、任何地点。并将G()
作为默认操作。
还有
您可以使用包含大量代码p(1)的整个程序,并将该代码转换为:
var myPromise = $q.reject();
P; // inline the program's code
myPromise.then(null, function(){}); // attach a handler
太好了,所以我能做到,所以
现在,我们的神奇机器可以获取任意程序p,并检测myPromise
是否添加了拒绝处理程序。现在,当且仅当P
不包含无限循环(即它停止)时,就会发生这种情况。因此,我们检测是否添加了catch处理程序的方法被简化为停止问题。这是不可能的(2)
因此,一般来说,不可能检测到.catch
处理程序是否附加到promise。
别再胡言乱语了,我想要一个解决方案
反应不错!像许多问题一样,这个问题在理论上是不可能的,但在实践中足够容易解决实际情况。这里的关键是一个启发式:
如果错误处理程序没有附加在微任务中(Angular中的摘要),则永远不会附加错误处理程序,我们可以触发默认处理程序。
这大致是:您从不异步.then(null, function(){})
。Promise是异步解析的,但处理程序通常是同步附加的,所以这很好。
// keeping as library agnostic as possible.
var p = myPromiseSource(); // get a promise from source
var then = p.then; // in 1.3+ you can get the constructor and use prototype instead
var t = setTimeout(function(){ // in angular use $timeout, not a microtask but ok
defaultActionCall(p);// perform the default action!
});
// .catch delegates to `.then` in virtually every library I read so just `then`
p.then = function then(onFulfilled, onRejected){
// delegate, I omitted progression since no one should use it ever anyway.
if(typeof onRejected === "function"){ // remove default action
clearTimeout(t); // `timeout.cancel(t)` in Angular
}
return then.call(this, onFulfilled, onRejected);
};
就这些吗
好吧,我只想补充一点,需要这种极端方法的情况很少。在讨论将拒绝跟踪添加到io时,一些人建议,如果一个承诺在没有catch
的情况下被拒绝,那么整个应用程序可能会终止。所以要格外小心:)
(1)假设p不包含变量myPromise,如果它将myPromise重命名为p不包含的东西
(2)当然-可以说,为了检测myPromise
得到拒绝处理程序,读取p的代码而不运行它就足够了。形式上,我们说我们把P中的每个return
和其他形式的终止都改为return myPromise.then(null, function(){})
,而不是简单地把它放在最后。通过这种方式,"条件性"得以体现