我试图使用 Promise 强制序列化一系列 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++);
});
});
工作演示:http://jsfiddle.net/jfriend00/4hfyahs3/ http://jsfiddle.net/jfriend00/4hfyahs3/
但是,这会构建一个可能永无止境的承诺链,因为变量p
存储最后一个承诺的信息永远不会被清除。每一次新的行动都与之前的承诺挂钩。所以,我在想,为了良好的内存管理,我应该能够检测到何时没有更多内存.then()
剩下的处理程序在当前值上运行p
然后我可以重置值p
,确保先前的 Promise 处理程序链可能在闭包中保存的任何对象都符合垃圾回收的条件。
所以,我想知道在给定的情况下我怎么知道.then()
处理程序没有更多.then()
在这个链中调用处理程序,因此,我可以这样做p = Promise.resolve()
重置p
并释放之前的承诺链,而不是不断地添加它。
有人告诉我,“良好”的承诺实现不会导致无限增长的承诺链中积累内存。但是,显然没有标准要求或描述这一点(除了良好的编程实践),并且我们有很多新手 Promise 实现,因此我尚未决定依赖这种良好行为是否明智。
我多年的编码经验表明,当实现是新的时,缺乏所有实现都以某种方式运行的事实,并且没有规范表明它们应该以这种方式运行,那么以“安全”的方式编写代码可能是明智的尽可能。事实上,仅仅围绕不确定的行为进行编码通常比测试所有相关的实现以了解它们的行为要少得多。
本着这种精神,这是我的代码的实现,在这方面似乎是“安全的”。它只是为每个保存全局最后一个承诺变量的本地副本.then()
处理程序,当那个.then()
处理程序运行,如果全局 Promise 变量仍然具有相同的值,那么我的代码没有将任何更多项目链接到它上面,所以这必须是当前的最后一个.then()
处理程序。它似乎工作在这个jsFiddle http://jsfiddle.net/jfriend00/qtbxq0et/:
// 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() {
var origP = p = p.then(function() {
return delay(v++);
}).then(function() {
if (p === origP) {
// no more are chained by my code
log("no more chained - resetting promise head");
// set fresh promise head so no chance of GC leaks
// on prior promises
p = Promise.resolve();
v = 1;
}
// clear promise reference in case this closure is leaked
origP = null;
}, function() {
origP = null;
});
});
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)