jquery promises可以在解决之前进行垃圾收集吗?

时间:2018-02-20 02:36:32

标签: javascript jquery promise

请考虑以下事项:

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)

3 个答案:

答案 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)

内森,封闭是关于标识符的吗?因此parallelLoad()引用了listFoolistFooey标识符(作为函数),创建了两个闭包。这些关闭将保持不变,直到(至少)每个功能完成并解决。这意味着parallelLoad()是执行上下文,尚未完成。该过程的下一步是.then()以响应解决方案。

这意味着执行上下文(parallelLoad())是在parallelLoad()调用时建立的,并且在.then()中的所有代码都完成之前不会更改,这是一个安全的范例。< / p>

enter image description here