我总是要调用JQuery Deferred.resolve或Deferred.reject吗?

时间:2013-12-19 03:28:21

标签: javascript jquery

因此,如下面的代码,它只处理ajax调用成功案例,如果ajax调用失败,则忽略它,并且永远不会调用deferred.reject()。因此,如果我们遇到失败的情况,jQuery中的任何事件监听器都将永远保持导致内存泄漏吗?

$.when(loadSomething).done(function() {
    // ...
});

function loadSomething() {
    var deferred = $.Deferred();

    // Only deal with the success case,
    // If the ajax call failed, it is ignored and the deferred.reject() will never be invoked.
    // So if we meet the failed case, will there any event listener inside jQuery will be keeped 
    // forever?
    ajaxCallToLoad(onResult);

    function onResult() {
        deferred.resolve();
    }

    return deferred.promise();
}

2 个答案:

答案 0 :(得分:0)

要回答您的真实问题,如果您在代码中某处保留对延迟和/或承诺的引用,则只会泄漏内存,无论您是否解决或拒绝延迟。如果没有引用,那么它将像平常一样被垃圾收集。

那就是说,我认为在这种情况下,而不是手动构建Deferred,您应该使用.then方法允许您转换/过滤结果。为了这个例子,让我们创建一个名为load的方法,该方法只是随机解析或拒绝延迟,类似于可能失败的ajax请求。

function load() {
    return $.Deferred(function( dfr ) {
       if ( Date.now() % 2 ) {
          dfr.resolve( 1 );
       }
       else {
          dfr.reject( "OHNO!" );
       }
    }).promise();
}

你现在能够使用它。然后过滤它:

var filteredResult = load().then(function( result ) {
    return result * 2;
});

filteredResult现在是一个承诺,如果解决了加载,它会使原始结果加倍,因此filterResult.done( console.log.bind( console ) )会将2打印到控制台。如果负载失败/被拒绝,那么失败处理程序仍然可以正常工作。

答案 1 :(得分:0)

  

因此,如果我们遇到失败的情况,jQuery中是否会有任何事件监听器永远会导致内存泄漏?

几乎肯定不会。

但是,如果你这样做,你明确地使用了承诺语义,但随后违反了承诺合同。那是不好的做法。你必须选择“最佳实践”:

  1. 继续使用承诺,但坚持合同。更新ajaxCallToLoad以便它也会通知您失败,并在发生这种情况时致电reject。 (如果ajaxCallToLoad正在使用jQuery的$.ajax函数,则可以使用jqXHR返回的$.ajax对象;它实现Promise。)

    < / LI>
  2. 如果您不想履行承诺合同,只需使用正常的“成功”回调而不是承诺。