jfr*_*d00 5 javascript asynchronous promise
我试图使用promises强制序列化一系列Ajax调用.每次用户按下按钮时,这些Ajax调用都会成为一个.我可以成功地序列化这样的操作:
// sample async function
// real-world this is an Ajax call
function delay(val) {
log("start: ", val);
return new Promise(function(resolve) {
setTimeout(function() {
log("end: ", val);
resolve();
}, 500);
});
}
// initialize p to a resolved promise
var p = Promise.resolve();
var v = 1;
// each click adds a new task to
// the serially executed queue
$("#run").click(function() {
// How to detect here that there are no other unresolved .then()
// handlers on the current value of p?
p = p.then(function() {
return delay(v++);
});
});
Run Code Online (Sandbox Code Playgroud)
工作演示:http://jsfiddle.net/jfriend00/4hfyahs3/
但是,这构建了一个可能永无止境的承诺链,因为p
永远不会清除存储最后一个承诺的变量.每一项新业务都只是扼杀了先前的承诺.所以,我认为为了良好的内存管理,我应该能够检测到什么时候没有.then()
剩余的处理程序继续运行当前值,p
然后我可以重置值p
,确保前一个链的任何对象承诺处理程序可能已关闭,将有资格进行垃圾回收.
所以,我想知道如何在给定的.then()
处理程序中知道在.then()
这个链中没有更多的处理程序被调用,因此,我可以做到p = Promise.resolve()
重置p
并释放先前的promise链而不是不断添加到它上面.
mxd*_*ois -1
您可以将承诺推入数组并使用Promise.all
:
var p = Promise.resolve,
promiseArray = [],
allFinishedPromise;
function cleanup(promise, resolvedValue) {
// You have to do this funkiness to check if more promises
// were pushed since you registered the callback, though.
var wereMorePromisesPushed = allFinishedPromise !== promise;
if (!wereMorePromisesPushed) {
// do cleanup
promiseArray.splice(0, promiseArray.length);
p = Promise.resolve(); // reset promise
}
}
$("#run").click(function() {
p = p.then(function() {
return delay(v++);
});
promiseArray.push(p)
allFinishedPromise = Promise.all(promiseArray);
allFinishedPromise.then(cleanup.bind(null, allFinishedPromise));
});
Run Code Online (Sandbox Code Playgroud)
或者,由于您知道它们是按顺序执行的,因此您可以让每个完成回调从数组中删除该承诺,并在数组为空时重置承诺。
var p = Promise.resolve(),
promiseArray = [];
function onPromiseComplete() {
promiseArray.shift();
if (!promiseArray.length) {
p = Promise.resolve();
}
}
$("#run").click(function() {
p = p.then(function() {
onPromiseComplete();
return delay(v++);
});
promiseArray.push(p);
});
Run Code Online (Sandbox Code Playgroud)
编辑:如果数组可能会变得很长,那么您应该选择第一个选项 b/c,移动数组的时间复杂度为 O(N)。
编辑:正如您所指出的,没有理由保留阵列。计数器就可以正常工作。
var p = Promise.resolve(),
promiseCounter = 0;
function onPromiseComplete() {
promiseCounter--;
if (!promiseCounter) {
p = Promise.resolve();
}
}
$("#run").click(function() {
p = p.then(function() {
onPromiseComplete();
return delay(v++);
});
promiseCounter++;
});
Run Code Online (Sandbox Code Playgroud)