发布于: 代码组织

Deferreds

从高层次来看,deferreds 可以被认为是表示异步操作的一种方式,这些操作可能需要很长时间才能完成。它们是阻塞函数的异步替代方案,其基本思想是,与其让应用程序阻塞以等待某个请求完成并返回结果,不如立即返回一个 deferred 对象。然后,您可以将回调附加到 deferred 对象:一旦请求实际完成,这些回调将被调用。

link Promises

以其最基本的形式,“promise”是一种模型,它为软件工程中的延迟(或未来)结果概念提供了解决方案。它背后的主要思想是我们已经讨论过的:与其执行可能导致阻塞的调用,不如返回一个未来值的 promise,该 promise 最终会被满足。

如果一个例子有所帮助,请考虑您正在构建一个严重依赖第三方 API 数据的 Web 应用程序。面临的一个常见问题是在给定时间对 API 服务器延迟的未知了解,因此应用程序的其他部分可能会被阻止运行,直到返回来自它的结果。Deferreds 为这个问题提供了一个更好的解决方案,一个没有“阻塞”效果并且完全解耦的解决方案。

Promises/A 提案定义了一个名为 "then" 的方法,可用于向 promise 注册回调,从而在未来结果可用时获取它。处理返回 promise 的第三方 API 的伪代码可能如下所示

1
2
3
4
5
6
7
8
9
10
11
12
13
var promise = callToAPI( arg1, arg2, ...);
promise.then(function( futureValue ) {
// Handle futureValue
});
promise.then(function( futureValue ) {
// Do something else
});

此外,一个 promise 最终实际上可以处于两种不同的状态

  • Resolved(已解决):在这种情况下数据可用
  • Rejected(已拒绝):在这种情况下出了问题,没有值可用

幸运的是,"then" 方法接受两个参数:一个用于 promise 被 resolved 时,另一个用于 promise 被 rejected 时。如果我们回到伪代码,我们可以做以下事情

1
2
3
4
5
6
7
8
9
promise.then(function( futureValue ) {
// We got a value
}, function() {
// Something went wrong
});

在某些应用程序中,需要返回多个结果,应用程序才能继续运行(例如,在用户能够选择他们感兴趣的选项之前,在屏幕上显示一组动态选项)。在这种情况下,存在一个名为 "when" 的方法,可用于在所有 promise 都完全实现后执行某个操作

1
2
3
4
5
6
7
8
9
when(
promise1,
promise2,
...
).then(function( futureValue1, futureValue2, ... ) {
// All promises have completed and are resolved
});

一个很好的例子是您可能正在运行多个并发动画的场景。如果不跟踪每个回调在完成时触发,就很难真正确定所有动画何时完成运行。然而,使用 promise 和 "when",这非常简单,因为您的每个动画都可以有效地表示“我们承诺一旦完成就会通知您”。由此产生的复合结果意味着在动画完成后执行单个回调是一个简单的过程。例如

1
2
3
4
5
6
7
8
9
10
11
var promise1 = $( "#id1" ).animate().promise();
var promise2 = $( "#id2" ).animate().promise();
when(
promise1,
promise2
).then(function() {
// Once both animations have completed
// we can then run our additional logic
});

这意味着人们可以编写基本上可以执行而无需同步的非阻塞逻辑。与其直接将回调传递给函数(这可能导致紧密耦合的接口),不如使用 promise 来分离同步或异步代码的关注点。