$q:默认拒绝处理程序 [英] $q: default reject handler
问题描述
我想返回一个 $q 实例,以便如果客户端不使用拒绝处理程序调用then",则运行默认的一个.
I want to return a $q instance so that if clients don't call 'then' with a reject handler, then a default one runs.
例如假设默认是 alert(1)
然后 mypromise.then(function(result){...})
会警告 1 但 mypromise.then(null, function(reason){alert(2)})
将警告 2
Then mypromise.then(function(result){...})
will alert 1 but mypromise.then(null, function(reason){alert(2)})
will alert 2
推荐答案
让我们假设有一种方法可以做到这一点.
所以我们有一个神奇的机器,它总能找出 .then
是否使用函数的第二个参数来调用特定的 promise.
Let's assume there was a way to do that.
So we have a magical machine that can always find out if .then
is called with a function second argument for a specific promise or not.
这样你就可以检测到是否有人这样做了:
So you can detect if someone did:
myPromise.then(..., function(){ F(); });
随时随地.并将 G()
作为默认操作.
At any point from anywhere at any time. And have G()
as a default action.
您可以将包含大量代码 P (1) 的整个程序转换为:
You could take a whole program containing lots of code P (1) and convert that code to:
var myPromise = $q.reject();
P; // inline the program's code
myPromise.then(null, function(){}); // attach a handler
太好了,所以我可以这样做,所以?
好吧,现在我们的魔法机器可以接收任意程序 P 并检测 myPromise
是否添加了拒绝处理程序.现在,当且仅当 P
不包含无限循环(即它停止)时才会发生这种情况.因此,我们检测是否添加了 catch 处理程序的方法是减少到停机问题.这是不可能.(2)
Great, so I can do that, so?
Well, now our magical machine can take an arbitrary program P and detect if myPromise
had a rejection handler added to it. Now this happens if and only if P
does not contain an infinite loop (i.e. it halts). Thus, our method of detecting if a catch handler is ever added is reduced to the halting problem. Which is impossible. (2)
一般来说 - 不可能检测到 .catch
处理程序是否曾经附加到承诺.
So generally - it is impossible to detect if a .catch
handler is ever attached to a promise.
反响不错!像许多问题一样,这个问题理论上是不可能的,但实际上很容易解决实际案例.这里的关键是启发式:
Good response! Like many problems this one is theoretically impossible but in practice easy enough to solve for practical cases. The key here is a heuristic:
如果微任务中没有附加错误处理程序(Angular 中的摘要) - 永远不会附加任何错误处理程序,我们可以改为触发默认处理程序.
If an error handler is not attached within a microtask (digest in Angular) - no error handlers are ever attached and we can fire the default handler instead.
大致是:你从不 .then(null, function(){})
异步.Promise 是异步解析的,但处理程序通常是同步附加的,所以这很好用.
That is roughly: You never .then(null, function(){})
asynchronously. Promises are resolved asynchronously but the handlers are usually attached synchronously so this works nicely.
// 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
的情况下被拒绝,那么整个应用程序可能会终止.所以要格外小心:)
Is that all?
Well, I just want to add that cases where this extreme approach is needed are rare. When discussing adding rejection tracking to io - several people suggested that if a promise is rejected without a catch
then the whole app should likely terminate. So take extra care :)
(1) 假设 P 不包含变量 myPromise,如果它确实将 myPromise 重命名为 P 不包含的内容.
(2) 当然 - 可以说只要读取 P 的代码而不运行它就足以检测 myPromise
是否获得拒绝处理程序.正式地说,我们将 P 和其他终止形式中的每个 return
更改为 return myPromise.then(null, function(){})
而不是简单地将其放入结束.这样就捕获了条件".
(2) Of course - one can say that it is enough to read the code of P and not run it in order to detect myPromise
gets a rejection handler. Formally we say that we change every return
in P and other forms of termination to a return myPromise.then(null, function(){})
instead of simply putting it in the end. this way the "conditionality" is captured.
这篇关于$q:默认拒绝处理程序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!