简体   繁体   中英

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. So if we meet the failed case, will there any event listener inside jQuery will be keep forever to cause memory leak?

$.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. 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. 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.

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:

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. 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?

Almost certainly not.

But if you do that, you're explicitly using promise semantics but then breaking the promise contract. 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. (If ajaxCallToLoad is using jQuery's $.ajax function, you could just use the jqXHR object that $.ajax returns; it implements Promise .)

  2. If you don't want to fulfill the promise contract, just use a normal "success" callback rather than a promise.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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