[英]Force jQuery Deferred to wait until Ajax complete in “then” handler
在某些情況下,我認為我需要使用“ then”處理程序創建一個Deferred對象,但是要等到“ then”處理程序完成其自己的承諾后,再繼續。
用例是一個記錄對象,上面的功能是它的save方法。 記錄對象具有名為saveQueue的屬性,該屬性在記錄的實例化時設置為$ .Deferred()。 應該對saveQueue進行resolve調用,以確保那里的Deferred總是盡可能快地執行附加到它的每個新處理程序。 您可以在短時間內連續多次保存記錄,但這些調用會一次又一次地運行,並且不會重疊。
我正在使用Deferred來排隊Ajax調用,以便直到上一個調用完成后才能運行。 但是,從同一個方法中,我想返回一個可以由jQuery Ajax對象解析/拒絕的Deferred,如下所示:
record.saveQueue = $.Deferred();
self.save = function( record ){
var deferredAction = $.Deferred();
deferredAction.then(function() {
return $.post("/example_save_endpoint");
});
record.saveQueue.always(function(){
deferredAction.resolve();
}).resolve();
return deferredAction;
}
但是,當我使用此代碼時, deferredAction
承諾始終會最終resolved
,大概是因為#then處理程序返回的是“待處理”(因此是非拒絕)承諾。 是否有任何方法可以迫使延遲者在解決/拒絕之前等待Ajax承諾完成? 還是有另一種更好的方法來穿針?
我可能會選擇不這樣做,但是延遲/承諾確實可以用作排隊設備。
您需要對已經嘗試的內容進行細微的變化?
self.queue = $.when();//A resolved promise, used to form a queue of functions in a .then() chain.
self.save = function(data) {
var dfrd = $.Deferred();//A Deferred dedicated to this particular save.
self.queue = self.queue.then(function() {
return $.post("/example_save_endpoint", data) //Make the AJAX call, and return a jqXHR to ensure the downstream queue waits for this jqXHR to resolve/reject.
.then(dfrd.resolve, dfrd.reject) //Resolve/reject the Deferred for the caller's benefit
.then(null, function() {
//Force failure down the success path to ensure the queue is not killed by an AJAX failure.
return $.when();//Return a resolved promsie, for the queue's benefit.
});
});
return dfrd.promise();//allow the caller to do something when the AJAX eventually responds
}
有關說明,請參見代碼中的注釋
您的想法可能有效,但是
.resolve()
來解決隊列,而只能使用已解決的諾言來初始化該隊列。 record.saveQueue
上排隊 ,需要在每個方法調用上進行更改(覆蓋),以表示最新請求的結束。 而且我們不需要為此延期 ,因為我們可以處理 $.post
返回的承諾 。
所以使用這個:
var emptyQueue = $.when(undefined); // an already fulfilled promise as the start
// equivalent: = $.Deferred().resolve().promise();
function startQueue() {
return emptyQueue; // yes, this delibaretely returns a constant, the begin
// of the queue always looks the same (and is never mutated)
}
// every time you create a record, do
record.saveQueue = startQueue();
// and use that in your methods:
this.save = function(record) {
var queuedRequestResult = record.saveQueue.then(function() {
return $.post("/example_save_endpoint");
// ^^^^^^ promises chain :-)
});
// Magic happens here:
record.saveQueue = queuedRequestResult // we swap the previous queue promise for a new
// one that resolves only after the request
.then(startQueue, startQueue); // and make sure it then starts with a fresh
// queue, especially when the request failed
//.then(null, startQueue) is similar, except unnecessarily remembering the last result
return queuedRequestResult;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.