我想发送 Ajax 请求并在数据到达时执行一些不相关的操作。完成操作后,我喜欢等待 Ajax 完成并执行另一个操作。
具体来说,让我们看一个简单的例子:
$.ajax({url: "/reqA"})
.done(updateA)
.done($.ajax("/reqB").done(updateB))
.done(updateFinal)
updateFinal
应在同步 updateA
和异步 /reqB
完成后以及同步 updateB
之后执行。
上面的代码是错误的,因为所有后续的 .done()
都是根据 /regA
的 promise 运行的,并且竞争条件发生在 updateB
和 之间>更新最终
。
我可以用 .then
修复代码:
$.ajax({url: "/reqA"})
.done(updateA)
.then($.ajax("/reqB").done(updateB))
.done(updateFinal)
但接下来我想在发送请求/reqB
后运行updateA
(因为JS引擎单线程和updateA
执行阻塞了异步进程/reqB
!!).
以下代码不起作用:
$.ajax({url: "/reqA"})
.then($.ajax("/reqB").done(updateB))
.done(updateA)
.done(updateFinal)
因为updateA
的执行会延迟到updateB
的执行!!
我认为这个问题可以用 $.when
函数解决,但是 updateA
不是 promise ,我在官方 $.when 文档中没有看到执行顺序保证.它可能看起来像:
$.ajax({url: "/reqA"})
.then(
$.when(
$.ajax("/reqB").done(updateB),
fakeResolvedPromiseWrapperAroundSyncFunc(updateA)
)
).done(updateFinal)
jQuery 库中是否有任何标准的fakeResolvedPromiseWrapperAroundSyncFunc
解决方案?
在启动异步并稍后加入异步调用结果后运行同步代码的任何其他路径?
最佳答案
在您的 .done()
和 .then()
处理程序中,您需要传递函数 REFERENCES,而不仅仅是调用括号中的函数,以便能够控制执行时间。
在 promise 链中,您可以将同步函数或异步函数作为 .then()
处理程序传递。如果你传递一个异步函数,它只需要返回一个 promise,然后那个 promise 就会被插入到 promise 链中。同步函数将在轮到它时被调用,然后链中的下一步将紧随其后(因为它是同步的)。
例如,改变这个:
$.ajax({url: "/reqA"})
.done(updateA)
.done($.ajax("/reqB").done(updateB))
.done(updateFinal)
为此:
$.ajax({url: "/reqA"})
.then(updateA)
.then(function() {
return $.ajax("/reqB").then(updateB)
}).then(updateFinal);
或者,这可以写成:
$.ajax({url: "/reqA"})
.then(updateA)
.then(function() {
return $.ajax("/reqB");
}).then(updateB)
.then(updateFinal);
这将执行 ajax 函数,当 Ajax 调用完成时,它将执行 updateA()
。同步 updateA()
完成后,它将调用匿名函数,然后执行/reqB ajax 调用。当该 ajax 调用完成时,它将执行 updateB()
。 updateB()
完成后,将调用 updateFinal()
。
然后,改变这个:
$.ajax({url: "/reqA"})
.then($.ajax("/reqB").done(updateB))
.done(updateA)
.done(updateFinal)
为此:
$.ajax({url: "/reqA"})
.then(function() {
return $.ajax("/reqB").then(updateB);
}).then(updateA)
.then(updateFinal)
当您像以前一样直接在括号内执行函数时,它会被立即调用,执行该函数的返回结果将作为 .then()
处理程序传递。当您传递一个函数引用时,.then()
基础架构可以稍后调用该函数。
您使用 $.when()
也可以。当您想并行执行多个项目并想知道它们何时全部完成时使用它。上面的代码建议做序列化执行(一个接着一个)。
至于混契约(Contract)步和异步代码,可以完美地工作。序列中的第一个操作必须创建一个 promise ,您可以从中链接一个 .then()
处理程序。之后,任何给定的 .then()
处理程序的回调可以执行以下任何操作:
它可以是同步的并返回一个常规值。这个值成为 promise 链的解析值,然后调用后续的
.then()
处理程序将该值传递给他们。它可以是同步的并且不返回值。 promise 链在那一点和下一个
.then( )
链中的处理程序将被调用。它可以是同步的并抛出异常。异常成为当前 promise 和任何附加的
.then()
拒绝处理程序的拒绝值,而不是解析处理程序被调用。它可以是异步的并返回一个 promise。 这个新的 promise 被插入到链中并且随后的
.then()
处理程序不会被调用,直到这个新的 promise 兑现。是否调用后续的 resolve 或 reject 处理程序将取决于此新 promise 是 resolve 还是 rejects。它可以是异步的,不返回任何东西或返回一个常规(非 promise )值。在这种情况下,启动了一个新的异步操作,但它对当前 promise 链,因为没有返回与新异步操作相关的 promise 。这个新的异步操作只是按照自己的节奏自行运行,当它完成时对当前的 promise 链没有影响。由于
.then()
处理程序没有返回任何 promise ,因此当前的 promise 就像描述的同步处理程序一样继续进行
关于javascript - 同步函数和异步延迟 jQuery 对象的混合,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34646117/