簡體   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