2011-06-06 56 views
6

所以在使用jQuery延遲和$.when並行加載許多對象。jquery推遲轉入失敗

$.when(
    a.ajax(), b.ajax(), c.ajax() 
).then(
    //do something when all are complete 
    complete(); 
); 

現在,b.ajax()有時會失敗,但我實際上不在乎。我只想等到所有的調用都完成之後再調用complete()。

不幸的是,只要b失敗,when()拒絕,並且從不觸發then()回調。這是AFAIK對$.when()的預期行爲,但在這種情況下適合我。

我想有效的方式說:

$.when(
    a.ajax(), b.ajax().fail(return success), c.ajax() 
).then(...) 

或者可能存在使用when(),或更合適的結構以不同的方式?

$.onCompleteSucceed = function(oldDfd) { 
    var newDfd = $.Deferred(); 

    oldDfd.always(newDfd.resolve); 

    return newDfd.promise(); 
} 

然後,您可以換適當的調用這個方法:

+0

@Ates我認爲你的刪除答案可以通過在返回之前解析新的延遲對象來解決。 – Alnitak 2011-06-20 15:48:14

+0

[$ .Deferred:如何檢測何時執行每個承諾]的可能重複(http://stackoverflow.com/q/19177087/1048572) – Bergi 2015-07-14 11:19:04

回答

1

所以我想通了,最終,看到我對其他人有同樣問題的答案:

how to fool jqXHR to succeed always

lonesomeday的答案很整潔,但並不完全一樣。

+0

從jQuery 1.8開始,管道已被棄用。參見[jQuery Deferred then](https://api.jquery.com/deferred.then/)中的書寫。 – Griffin 2015-05-13 15:39:49

1

你可以通過包裝$.Deferred對象建立$.onFailSucceed很容易

$.when(
    a.ajax(), $.onCompleteSucceed(b.ajax()), c.ajax() 
).then(...) 
+0

不錯的解決方案,除了它不會傳遞'b .ajax()'到'.then()'處理程序中。 – Alnitak 2011-06-20 15:52:04

3

這裏比黑客入侵成功要好。

鮮爲人知的事實是,$ .when()將在任何一個參數失敗時立即執行then()回調。這是設計。引述文件:

http://api.jquery.com/jQuery.when/

在該Deferreds的一個被拒絕的多Deferreds情況下,jQuery.when立即觸發了它的主人已延期failCallbacks。請注意,在這一點上,某些延期付款可能仍未解決。如果您需要爲這種情況執行額外的處理,例如取消任何未完成的ajax請求,則可以將引用保留在關閉中的基礎jqXHR對象中,並在failCallback中檢查/取消它們。

實際上並沒有內置的等待,直到所有人都完成了,無論他們的成功/失敗狀態。

因此,我建立了一個$。whenAll()爲您:)它一直等待,直到所有的人解決,一個或其他方式:

http://jsfiddle.net/InfinitiesLoop/yQsYK/

+1

謝謝你。 – tomswift 2013-01-16 20:24:17

5

如果你想捕捉一個承諾的失敗,將其轉換成一個成功的,可以使用failFilter的then返回一個解決的承諾,就像這樣:

deferredCall.then(function(answer) { 
    // this is success. you might transform the answer here. 
    return transformed; 
}, function() { 
    // this is a fail. you might resolve the fail with an empty object. 
    return $.Deferred().resolve({}).promise(); 
}); 

這樣做將確保鏈條能繼續過去的失敗不間斷。

所以,你的例子,你可以這樣做:

$.when([ 
    a.ajax(), 
    b.ajax().then(function(answer) { 
     return answer; 
    }, function() { 
     return $.Deferred().resolve({}).promise(); 
    }), 
    c.ajax() 
]).then(function(results) { 
    // etc. 
}); 

例2:在我的應用程序,我有時用then獲取相關數據特定實體並允許404的可能性表示沒有這樣的合作關係:

getEntity(id).then(function(entity) { 
    return getAssociation(id).then(function(association) { 
     entity.association = association; 
     return entity; 
    }, function() { 
     entity.association = null; 
     return $.Deferred().resolve(entity).promise(); 
    }); 
}).done(function(entity) { 
    // etc. 
}); 

請注意,舊的答案使用pipe方法建議。從jQuery 1.8開始,此方法已被棄用。

+0

任何想法,爲什麼這不起作用?我試了它,它仍然失敗的情況下管 – Andrey 2016-01-14 13:06:28

+0

重要的是,你的失敗處理程序(「then」的第二個功能)返回一個已解決的承諾。一個失敗的承諾或任何價值而不是一個承諾將允許該鏈繼續到另一個失敗處理程序。 – Griffin 2016-01-14 18:29:55