$q:默认拒绝处理程序

$q: default reject handler

本文关键字:处理 程序 拒绝 默认      更新时间:2024-03-25

我想返回一个$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(){}),而不是简单地把它放在最后。通过这种方式,"条件性"得以体现