$q:默认拒绝处理程序
$q: default reject handler
我想 return 一个 $q 实例,这样如果客户不使用拒绝处理程序调用 'then',那么将运行一个默认的。
例如假设默认值为 alert(1)
然后 mypromise.then(function(result){...})
会提醒 1 但 mypromise.then(null, function(reason){alert(2)})
会提醒 2
让我们假设有办法做到这一点。
所以我们有一台神奇的机器,它总能查明 .then
是否使用函数第二个参数调用来实现特定的承诺。
那又怎样?
所以你可以检测是否有人这样做了:
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 处理程序的方法是 reduced to the halting problem. Which is impossible。 (2)
所以通常 - 不可能检测到 .catch
处理程序是否曾经附加到承诺。
别胡说八道了,我要解决办法!
反响好!与许多问题一样,这个问题理论上 是不可能的,但在实践中很容易解决实际案例。这里的关键是启发式:
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 是异步解决的,但处理程序通常是同步附加的,所以这很好用。
// 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) 当然 - 可以说阅读 P 的代码就足够了,而不是 运行 它是为了检测 myPromise
获得拒绝处理程序.正式地说,我们将 P 中的每个 return
和其他终止形式更改为 return myPromise.then(null, function(){})
而不是简单地将其放在最后。这样 "conditionality" 就被捕获了。
我想 return 一个 $q 实例,这样如果客户不使用拒绝处理程序调用 'then',那么将运行一个默认的。
例如假设默认值为 alert(1)
然后 mypromise.then(function(result){...})
会提醒 1 但 mypromise.then(null, function(reason){alert(2)})
会提醒 2
让我们假设有办法做到这一点。
所以我们有一台神奇的机器,它总能查明 .then
是否使用函数第二个参数调用来实现特定的承诺。
那又怎样?
所以你可以检测是否有人这样做了:
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 处理程序的方法是 reduced to the halting problem. Which is impossible。 (2)
所以通常 - 不可能检测到 .catch
处理程序是否曾经附加到承诺。
别胡说八道了,我要解决办法!
反响好!与许多问题一样,这个问题理论上 是不可能的,但在实践中很容易解决实际案例。这里的关键是启发式:
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 是异步解决的,但处理程序通常是同步附加的,所以这很好用。
// 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) 当然 - 可以说阅读 P 的代码就足够了,而不是 运行 它是为了检测 myPromise
获得拒绝处理程序.正式地说,我们将 P 中的每个 return
和其他终止形式更改为 return myPromise.then(null, function(){})
而不是简单地将其放在最后。这样 "conditionality" 就被捕获了。