请考虑以下事项:
function listFoo() {
return $.ajax(...);
}
function listFooey() {
return $.ajax(...);
}
function parallelLoad() {
//Note that we do *not* return the promise here.
$.when(
listFoo(), listFooey()
)
.then (function(fooResponse, fooeyResponse) {
console.log('then')
//doStuff
});
}
//Kick everything off and log
console.log('before parallelLoad');
parallelLoad();
console.log('after parallelLoad');
控制台上的典型输出是(jsfiddle):
before parallelLoad
after parallelLoad
then
前两个函数返回ajax Promise
,因此对它的引用不会丢失。但是,parallelLoad()
函数不会返回promise,所以当它被执行时,它会创建promise,立即返回,而promise似乎会立即超出范围。
在实践中,我没有看到这种模式出现问题,但我想知道这是否只是“运气”。
在上面的示例中,parallelLoad()
是“安全的”(假设ajax调用在没有服务器/网络错误的情况下运行)then
子句将始终执行?
或者是否存在争用条件,有时甚至可能无法启动ajax调用,或者在then
子句运行之前可能会对垃圾进行垃圾收集?
(目前我使用的是jQuery 3.3.1)
答案 0 :(得分:0)
那里没有问题,then
将始终执行。
这有一个明显的缺点是因为parallelLoad
承诺丢失,没有延续,你不能将任何其他事件链接到listFoo, listFooey
的成功或失败。
我认为承诺链式可能是引起混淆的原因。
以这种方式看待它,如果你像这样重写parallelLoad
(打破链条),
function parallelLoad() {
//Note that we do *not* return the promise here.
var whenPromise = $.when(listFoo(), listFooey());
whenPromise.then(function(fooResponse, fooeyResponse) {
console.log('then');
//doStuff
});
}
您现在可以很容易地看到then
部分只是另一行代码(带有回调)等待被调用,因此在完成之前不会进行垃圾回收。
then
被调用后,parallelLoad
将超出 你 的范围, 但是 对其中创建的promises和callback的引用仍然保留在内存中,直到Promise被解析/拒绝并调用回调。
答案 1 :(得分:0)
一般而言,无法解决且不再需要的承诺可以在解决之前进行垃圾收集。
然而,在您的示例中并非如此。即使没有明显的全局变量保持承诺,它仍然从正在运行的ajax请求中引用。 listFoo()
和listFooey()
创建的请求会使回调安装在它们上面,因为它们需要在完成后运行它们。反过来,这些回调引用了promises(或至少是它们的延迟部分)和安装在它们上的回调,因为它们需要解析promise并在它们运行时调用回调。反过来,这些回调引用了$.when
调用创建的promise(或延迟)以及安装在其上的回调,因为在所有内容都已解决之前仍然需要它们。只有在两个请求都完成并且所有回调都被执行后,一切都将被垃圾收集。
不可以,承诺将错过调用你的回调,因为在错误的时间收集了垃圾。
答案 2 :(得分:-1)