繁体   English   中英

我是否应该总是调用JQuery Deferred.resolve或Deferred.reject?

[英]Shall I always invoke either JQuery Deferred.resolve or Deferred.reject?

因此,如下面的代码所示,它仅处理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();
}

为了回答您的真实问题,只有在您维护对延迟和/或promise的引用时,才泄漏内存,无论您是否解析或拒绝延迟。 如果没有引用,那么它将像平常一样被垃圾收集。

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

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

您现在可以使用.then对其进行过滤,如下所示:

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

现在, filteredResult是一个承诺,如果解决了加载问题,它将使原始结果加倍,因此filterResult.done( console.log.bind( console ) )将向控制台显示2 如果加载失败/被拒绝,则失败处理程序仍将正常工作。

因此,如果遇到失败的情况,jQuery内是否会永久保留任何事件侦听器,从而导致内存泄漏?

几乎可以肯定。

但是,如果这样做,则显式地使用了Promise语义,但随后违反了Promise合同。 那是不好的做法。 您必须具有“最佳做法”选项:

  1. 继续使用承诺,但要遵守合同。 更新ajaxCallToLoad以便它也通知您失败,并在发生延迟时对您的延迟调用reject (如果ajaxCallToLoad使用的是jQuery的$.ajax函数,则可以只使用$.ajax返回的jqXHR对象;它实现Promise 。)

  2. 如果您不想履行承诺合同,只需使用常规的“成功”回调而不是承诺即可。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM