用户可以通过在UI中输入值来进行异步调用。
当用户更改UI中的值时,可能在调用提供给异步调用返回的promise的回调之前,会进行另一个异步调用。
正在使用的异步API返回基于Q的承诺。
如何优雅地取消原始调用,确保即使系统返回第一个调用的值,promise的.then
部分也不会使用该值调用(但最终会在第二个异步调用完成时调用)?
以前我遇到过这样的情况(node.js),我要么在做web请求,要么在做db请求。我有一个超时对象,我认为它是可以取消的(sry,不记得细节了),并且对它们都有承诺。因此,如果网页首先返回,我会取消超时并返回html。如果首先发生超时,我会将JSON中的"timedout"字段更新为yes,这样,如果web调用返回,它就会知道死亡。这有点令人震惊,因为有了这些承诺,我可以进入功能一次,实际上可以返回两次!
希望能帮助
-Tom
如果没有取消API,每个异步调用都将运行到完成,但如果您只想取消.then()函数,那么这是可行的。最直接的方法是计数器:
var counter = 0;
function onClick() {
counter++;
doAsyncCall().then(function(result) {
if (!--counter) {
myFunc(result);
}
});
}
但你要求优雅,所以也许一个更可重复使用的结构是这样的:
var idle;
function onClick(){
idle = Overtake(idle, doAsyncCall());
idle.then(myFunc).then(myOtherFunc);
}
可以这样实现:
function Overtaker(prior, callp) {
if (prior) {
prior.cancel();
}
var p;
p = new Promise(function(resolve, reject) {
callp.then(function(value) { return p && resolve(value); },
function(reason) { return p && reject(reason); });
});
this.cancel = function() { p = null; }
this.then = function(onFulfilled, onRejected) {
return p.then(onFulfilled, onRejected);
}
}
function Overtake(prior, p) {
return new Overtaker(prior, p);
}
我使用的是ES6 promise,但Q promise看起来很相似,所以希望它也能在那里工作。