简体   繁体   English

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

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

So as below code, it only deal with the ajax call success case, if the ajax call failed, it is ignored and the deferred.reject() will never be invoked. 因此,如下面的代码所示,它仅处理ajax调用成功的情况,如果ajax调用失败,则将其忽略,并且永远不会调用deferred.reject()。 So if we meet the failed case, will there any event listener inside jQuery will be keep forever to cause memory leak? 因此,如果遇到失败的情况,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();
}

To answer your real question, you will only leak memory if you're maintaining a reference to the deferred and/or promise somewhere in your code despite whether or not you resolve or reject the deferred. 为了回答您的真实问题,只有在您维护对延迟和/或promise的引用时,才泄漏内存,无论您是否解析或拒绝延迟。 If there are no references, then it'll be garbage collected like normal. 如果没有引用,那么它将像平常一样被垃圾收集。

That said, I think that in this case rather than manually constructing a Deferred, you should be using the .then method allows you to transform/filter the results. 就是说,我认为在这种情况下,您应该使用.then方法来转换/过滤结果,而不是手动构造Deferred。 For the sake of this example, lets create a method called load which is just randomly resolves or rejects a deferred, analogous to an ajax request that can potentially fail. 对于本示例,让我们创建一个称为load的方法,该方法只是随机解析或拒绝延迟的方法,类似于可能失败的ajax请求。

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

What you're now able to to is use .then to filter it like so: 您现在可以使用.then对其进行过滤,如下所示:

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

filteredResult is now a promise where if load was resolved, it doubles the original result, so filterResult.done( console.log.bind( console ) ) would print 2 to the console. 现在, filteredResult是一个承诺,如果解决了加载问题,它将使原始结果加倍,因此filterResult.done( console.log.bind( console ) )将向控制台显示2 If the load had failed/been rejected, then the failure handlers would still work appropriately. 如果加载失败/被拒绝,则失败处理程序仍将正常工作。

So if we meet the failed case, will there any event listener inside jQuery will be keep forever to cause memory leak? 因此,如果遇到失败的情况,jQuery内是否会永久保留任何事件侦听器,从而导致内存泄漏?

Almost certainly not. 几乎可以肯定。

But if you do that, you're explicitly using promise semantics but then breaking the promise contract. 但是,如果这样做,则显式地使用了Promise语义,但随后违反了Promise合同。 That's poor practice. 那是不好的做法。 You have to "best practices" options: 您必须具有“最佳做法”选项:

  1. Continue using promises, but stick to the contract. 继续使用承诺,但要遵守合同。 Update ajaxCallToLoad so that it also notifies you of failure, and call reject on your deferred when that happens. 更新ajaxCallToLoad以便它也通知您失败,并在发生延迟时对您的延迟调用reject (If ajaxCallToLoad is using jQuery's $.ajax function, you could just use the jqXHR object that $.ajax returns; it implements Promise .) (如果ajaxCallToLoad使用的是jQuery的$.ajax函数,则可以只使用$.ajax返回的jqXHR对象;它实现Promise 。)

  2. If you don't want to fulfill the promise contract, just use a normal "success" callback rather than a promise. 如果您不想履行承诺合同,只需使用常规的“成功”回调而不是承诺即可。

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

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