发布在:代码组织

延迟

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

链接 承诺

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

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

Promises/A 提议定义了一个名为“then”的方法,该方法可用于向承诺注册回调,从而在可用时获取未来结果。处理返回承诺的第三方 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
});

此外,承诺实际上最终可能处于两种不同的状态

  • 已解决:在这种情况下,数据可用
  • 已拒绝:在这种情况下,出现问题,并且没有可用值

值得庆幸的是,“then”方法接受两个参数:一个用于承诺已解决时,另一个用于承诺已拒绝时。如果我们回到伪代码,我们可能会做类似的事情

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

在某些应用程序中,在应用程序可以继续之前,必须返回几个结果(例如,在用户能够选择他们感兴趣的选项之前,在屏幕上显示一组动态选项)。在这种情况下,存在一个名为“when”的方法,该方法可用于在所有承诺完全兑现后执行某些操作

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 可以将同步或异步代码的关注点分开,而不是直接将回调传递给函数,这会导致紧密耦合的接口。