# Promis
不把自己程序的 continuation 传给第三方,而是希望第三方给我们提供了解其任务何时结束的能力,然后由我们自己的代码来决定下一步做什么。这种范式就称为 Promise。
# 未来值
运算 x y 假定了 x 和 y 都已经设定。
代码语言:javascript复制var x, y = 2;
console.log(x y);
把 x
和 y
当作未来值,并且表达了一个运算 add()
。这个运算(从外部看)不在意 x
和 y
现在是否都已经可用。
function add (getX, getY, cb) {
var x, y;
getX (function (xVal) {
x = xVal;
if (y != undefined) {
cb (x y);
}
});
getY (function (yVal) {
y = yVal;
if (x != undefined) {
cb (x y);
}
});
}
add(fetchX, fetchY, function (sum) {
console.log(sum);
});
为了统一处理现在 和将来 ,我们把它们都变成了将来 ,即所有的操作都成了异步的。
试试用 Promise 来表达 x
:
function add (xPromise, yPromise) {
return Promise.all([xPromise, yPromise])
.then(function (values) {
return values[0] values[1];
});
}
add(fetchX(), fetchY())
.then(
function (sum) {
console.log(sum);
},
function (err) {
console.log(err);
}
);
从外部看,由于 Promise 封装了依赖于时间的状态——等待底层值的完成或拒绝,所以 Promise 本身是与时间无关的。因此,Promise 可以按照可预测的方式组成(组合),而不用关心时序或底层的结果。
一旦 Promise 决议,它就永远保持在这个状态。此时它就成为了不变值 (immutable value),可以根据需求多次查看。
Promise 是一种封装和组合未来值的易于复用的机制。
# 完成事件
单独的 Promise 展示了未来值的特性。也可以从另外一个角度看待 Promise 的决议:一种在异步任务中作为两个或更多步骤的流程控制机制,时序上的 this-then-that。
在典型的 JavaScript 风格中,如果需要侦听某个通知,可以把对通知的需求重新组织为对 foo()
发出的一个完成事件 (completion event, 或 continuation 事件)的侦听。
使用回调的话,通知就是任务(foo()
)调用的回调。而使用 Promise 的话,把这个关系反转了过来,侦听来自 foo()
的事件,然后在得到通知的时候,根据情况继续。
foo (x) {
// 一些耗时的操作
}
foo(2022);
on (foo 'completion') {
// 一些操作
}
on (foo 'error') {
// 一些操作
}
调用 foo()
,然后建立了两个事件侦听 器,一个用于"completion" ,一个用于 "error" —— foo()
调用的两种可能结果。从本质上讲,foo()
并不需要了解调用代码订阅了这些事件,这样就很好地实现了关注点分离 。
function foo (x) {
// 一些耗时的操作
return listener;
}
var evt = foo(2022);
evt.on('completion', function () {
// 一些操作
});
evt.on('error', function () {
// 一些操作
});
复制