Promise就像薛定谔的猫
突然觉得Promise和薛定谔的猫有相似之处。
- 薛定谔的猫在密闭容器里,外面不清楚它的生死,只有打开盒子才知道。
- 一个Promise对象,外面不知道到它的状态,只有用then/catch方法才能知道。
薛定谔的猫:是指将一只猫关在装有少量镭和氰化物的密闭容器里。镭的衰变存在几率,如果镭发生衰变,会触发机关打碎装有氰化物的瓶子,猫就会死;如果镭不发生衰变,猫就存活。根据量子力学理论,由于放射性的镭处于衰变和没有衰变两种状态的叠加,猫就理应处于死猫和活猫的叠加状态。
MDN上Promise对象的定义:Promise 对象用于表示一个异步操作的最终完成 (或失败)及其结果值。
我们不考虑量子力学那玄妙的理论,单是引用将猫咪放入密闭盒子这个情景。猫咪初始状态是待定状态(pending)——生与死的叠加态。在某一个时刻变成塌缩成已兑现(fulfilled)状态——生,或者已拒绝(rejected)状态——死。
而在盒子外的我们,并不知道盒子里猫咪的状态,需要通过then/catch方法才能知道。
决定猫咪生死
接下来,我们进入关猫咪的盒子内部,此时我们就成了上帝,可以用resolve和reject控制猫咪的生死。
// 构造器接受一个名为"executor function"的函数。这个函数拥有了控制猫咪生死的权力。
new Promise((resolve, reject) => {
setTimeout(() => {
resolve('活');
}, 300);
});
这里,我们把制造一个Promise当成盒子内部的事,使用一个Promise对象当初盒子外部的事。分清了这两个视角,有助于我们理解Promise。
查看猫咪生死
我们先得到一个盒子(得到一个promise对象)。
// 从构造器得到
const promiseA = new Promise(...);
// 或者从原生api中得到
const promiseB = fetch(url);
// 或者从他人封装的方法得到
const promiseB = ajax(url);
我们需要一个方法,跟盒子联通起来,无论猫咪生死,都让我们知道。
// 通过then方法,它最多需要有两个参数:Promise 的成功和失败情况的回调函数。
promiseA
.then(()=> {
// 跟猫咪玩耍
}, () => {
// 给猫咪安葬
})
这样我们就放心了,无论猫咪怎样,我们都可以及时做出处理。
连接装猫的盒子
Promise的一大特性就是链式调用。then() 函数会返回一个和原来不同的新的 Promise。
const promise = playWithCat();
const promiseNew = promise.then(successCallback, failureCallback);
利用链式调用,连续执行两个或者多个异步操作
playWithCat().then(function(result) {
// 再把猫放一个新盒子里
return playWithCatAgian(result);
})
.then(function(newResult) {
// 再把猫放一个新盒子里
return playWithCatThird(newResult);
})
.then(function(finalResult) {
// 累了,让猫歇会
})
.catch(failureCallback);
then 里的参数是可选的,catch(failureCallback) 是 then(null, failureCallback) 的缩略形式。
链式调用很好的解决了回调地狱:
playWithCat(function(result) {
playWithCatAgian(result, function(newResult) {
playWithCatThird(newResult, function(finalResult) {
// 累了,让猫歇会
}, failureCallback);
}, failureCallback);
}, failureCallback);
小结
Promise的其他方法如Promise.all() 和 Promise.race() 。都可以类比成猫咪和盒子的故事。希望这样的类比可以让你更有效的理解Promise。加油共同学习吧。