【问题标题】:How to line up jQuery deferred objects?如何排列jQuery延迟对象?
【发布时间】:2016-01-20 08:41:25
【问题描述】:

我需要延迟每个 Ajax 调用,直到前一个函数 (hashcode.Sign()) 完成。不幸的是,我的代码不会等到hashcode.Sign() 完成,这会搞砸一切,因为该函数会创建一个新会话,并且它不能被覆盖以使事情正常工作。我该怎么做?我是 Deferred 对象的新手,所以请原谅我缺乏知识。

    for (var l = 0; l < fileArray.length; l++) {
        var d = new jQuery.Deferred();
        d.resolve(openDdoc(fileArray[l].url, $pid, fileArray[l].id));
        d.done(function() { console.log('done'); });
    }

    function openDdoc(url, pid, fid) {
        var def = new jQuery.Deferred();
        $.when(def).done(function() { console.log('Function completed!'); });
        def.resolve($.ajax({
                    url: '/open-ddoc',
                    type: 'post',
                    async: false,
                    data: {doc: url, pid: pid, fid: fid},
                }).done(function (data) {
                    hashcode.Sign();
                }).fail(function(data) {
                    console.log('this shit failed');
                }));
    }

hashcode.Sign() 函数包括更多的 Ajax 调用和对其他函数的调用。如果需要,我可以稍后包含它。我知道我可以使用 setTimeout() 解决所有这些问题,但这不是我的首选。

【问题讨论】:

  • 是的,请包括hashcode.Sign()。以正确的方式编写很重要。

标签: javascript jquery ajax jquery-deferred


【解决方案1】:

这不是很明显,但您寻求的顺序可以用fileArray().reduce(...) 的形式表示。

这种久经考验的模式在子标题“The Collection Kerfuffle”下概述了here。 (整篇文章很值得一读)。

fileArray.reduce(function(promise, file) {
    return promise.then(function() {
        return $.ajax({
            url: '/open-ddoc',
            type: 'post',
            async: true, // <<<<< always TRUE!!
            data: {doc: file.url, pid: $pid, fid: file.id}
        });
    }).then(function(data) {
        console.log(file.id + ': done');
        return hashcode.Sign(); // hashcode.Sign() must return a promise
    });
}, $.when()) // <<<<< resolved promise to get the chain started
.then(function() {
    console.log('all done');
});

在这种模式下,fileArray 的每个成员都被依次(同步)访问,每次访问时都会将新的.then() 添加到不断增长的 Promise 链中。

已解决的启动器承诺$.when() 使构造的链开始稳定,并按顺序进行 ajax 调用。

ajax 调用不需要在单独的函数中,除非它将在其他地方调用。

应该强调 hashcode.Sign()(我们理解为异步)必须以正确的方式编写,以便它返回有效的承诺。如果不是,则结算过程无法确保其异步性在继续之前完成。

【讨论】:

  • 只是指出显而易见的,// hashcode.Sign() must return a promise 可能是这个答案中更重要的一点之一。如果hashcode.Sign() 没有返回承诺,除了修复hashcode.Sign() 以返回承诺之外,您无能为力。
  • @KevinB,谢谢。是的,对你和我来说都是显而易见的,但也许不是 OP。我现在添加了一个脚注。当 OP 响应我对 hashcode.Sign() 代码的请求时,我将能够进行适当的编辑。如果您先到那里,请随时编辑我的答案。
  • 感谢您的可靠回复。我添加了corresponding function to PasteBin 供您查看。目前我必须承认,它并没有兑现承诺。
  • hashcode.Sign()hashcode.hashCreateResponseHandler() 需要一些工作。两者都必须返回承诺,所有执行异步操作的内部函数也必须返回。此外,.done().fail() 不具备“过滤”承诺的能力,因此您还需要将 .done(fn) 更改为 .then(fn),并将 .fail(fn) 更改为 .then(null, fn)
  • 我将return hashcode.Sign() 替换为return hashcode.Sign().then(function(res) { console.log(file.id+': done'); });。查看控制台,在第一个 hashcode.Sign() 完成所有操作之前,对 /open-ddoc 的后续 AJAX 调用仍然为时过早。但我现在明白了一般的想法。似乎 JS deferred 和 Promise 模式只是在我了解它们之前要破解的另一个问题。 :) 无论如何谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-12-17
  • 1970-01-01
  • 1970-01-01
  • 2012-06-13
  • 2011-06-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多