当前位置: 首页 > 知识库问答 >
问题:

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

晁开宇
2023-03-14

我有这样的情况,我相信我需要创建一个具有“然后”处理程序的延迟对象,但是要等到“然后”处理程序完成了它自己的promise之后再继续。

用例是一个记录对象,上面的功能是它的保存方法。记录对象有一个名为SaveQueue的属性,该属性设置为$。延迟()记录的实例化。SaveQueue上的解析调用应该确保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;
  }

但是,当我使用此代码时,延迟动作promise总是以已解决结束,这可能是因为#then处理程序正在返回一个“挂起”(因此不拒绝)promise。是否有任何方法可以迫使延迟的用户在解决/拒绝Ajaxpromise之前等待Ajaxpromise完成?还是有其他更好的方法来穿这根针?

共有2个答案

左丘季
2023-03-14

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

你需要对你已经尝试过的东西稍加改变。

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
}

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

乐正涵忍
2023-03-14

你的想法可能行得通,但是

  • 每次调用该方法时,不能使用.resolve()解析队列,而应仅使用已解析的promise对其进行初始化。

我们不需要任何延迟,因为我们可以处理$.post返回的promise。

所以用这个:

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;
}
 类似资料:
  • 我正在尝试将我的UIAlertViews更改为UIAlertController。我为它设置了这个操作: 但是,处理程序直到动作被点击大约一秒钟后才运行。有什么方法可以加快速度吗?

  • 问题内容: 我有一个jQuery Ajax请求,我想用文本输入调用它,因此我将其嵌套在里面。这很好。 但这有时表现为越野车。当我非常快速地输入一些文本时,我得到的输入单词的结果中省略了原始输入单词的最后几个字母(可能是浏览器的某些错误)。我希望在没有输入活动持续一秒钟的情况下发送ajax请求,如果我很快输入文本并休息一秒钟(意味着我进行了输入)。我怎样才能做到这一点? 问题答案: 听起来好像是从先

  • 如何在Vertx中处理延迟作业列表(实际上是数百个HTTP GET请求,到禁止快速请求主机的有限API)?现在,我正在使用此代码,它被阻止,因为Vertx一次启动所有请求。希望在每个请求之间有5秒的延迟来处理每个请求。

  • 我试图使用处理程序线程设置一个延迟的for循环。但是当我在for循环中设置处理程序线程时,我不能使用for循环的索引,因为它说它必须被称为final,但这也不起作用。有人知道怎么修吗?

  • 问题内容: 我最近在愚弄一些Ajax轮询技术。但是,似乎我无法从FireFox(3.6.7)中的对象覆盖处理程序。 在跟踪为什么FF在尝试访问时引发异常的问题时,我意识到这取决于是否调用了该方法。 换句话说,这是一个有效的示例(纯js,到目前为止没有jQuery): (这只是为了演示而进行了相当简化) 更好的说是可行的,可以在这里访问。如果我切换最后两行代码,FF会引发异常,基本上是告诉我不允许访

  • 问题内容: 因此,我将顺序的ajax链接在一起,以按顺序加载URL数组。最初,我使用代替,并且无论哪种方式都可以正常工作- 只要所有网址都存在。但是,由于可能会丢失文件,因此我想对此进行补偿,然后,最后通知用户丢失了哪些文件,以便更轻松地进行纠正。 但是,问题是,在丢失的文件/ 404上,代码会像应执行的那样执行,但随后退出循环,从而阻止了进一步的ajax调用。因此,我认为,我需要某种方式来处理并