我应该总是调用JQuery Deferred.resolve或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(); } 

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

几乎肯定不是。

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

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

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

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

也就是说,我认为在这种情况下,而不是手动构建一个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现在是一个承诺,如果解析了load,它会使原始结果加倍,所以filterResult.done( console.log.bind( console ) )会将2打印到控制台。 如果负载失败/被拒绝,那么失败处理程序仍然可以正常工作。