强制jQuery延迟等到Ajax在“then”处理程序中完成

我有这样的情况,我认为我需要使用“then”处理程序创建一个Deferred对象,但是等到“then”处理程序完成它自己的承诺后再继续。

用例是一个记录对象,上面的函数是它的保存方法。 记录对象有一个名为saveQueue的属性,在记录的实例化中设置为$ .Deferred()。 对saveQueue的解析调用应该确保Deferred总是会尽可能快地执行附加到它的每个新处理程序。 这个想法是你可以在短时间内在记录上多次调用save,但调用会一个接一个地运行,而不是重叠。

我正在使用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处理程序返回一个“挂起”(因而是非拒绝)的承诺。 在解决/拒绝之前,有没有办法强制Deferred等待Ajax承诺完成? 还是有另一种更好的方法来穿针吗?

你的想法可能有用,但是

  • 每次调用方法时都不能使用.resolve()来解析队列,而应该只使用已解析的promise来初始化队列。
  • 要实际在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; } 

我可能会选择不这样做,但延迟/承诺确实可以用作排队设备。

您需要对您已经尝试过的内容进行轻微(?)变化。

 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 } 

有关说明,请参阅代码中的注释