一、快速使用
const promise = new Promise((resolve,reject)=>{
//耗时、异步操作
if (Math.random()*100 > 20){//随机数模拟成功率
resolve("success");
}
else {
reject("fail");
}
});
promise.then((value)=>{
console.log("then: ",value);
})
.catch((error)=>{
console.log("catch: ",error);
})
.finally(()=>{
console.log("finally");
});
执行多次打印

以上代码就是我们常用的比较简单的Promise例子,在这里我们可以看到"finally"每一次都会被打印,而"success"总是在then方法里被打印,"fail"在catch中被打印,我们隐约能看到一点规律,resolve的值的在then方法中回调,reject的值在catch中,最后都走一个finally方法。这就是最简单的用法了。
二、Promise 是怎么工作的
我们先来解释下上面的代码,Promise的构造函数接收一个函数作为参数,生成一个Promise对象,这个函数中有两个入参,参数类型也是函数,这样听起来有点绕口,看代码比较直观。然后对象调用then方法,还有后面的catch、finally方法。
Promise是一个可以从异步函数同步返回的对象,我们可以在生成Promise实例时,把耗时操作带进去让他去异步执行,然后可以和写同步函数一样,通过Promise对象then方法接收处理resolve()或者reject()回调回来的值。这里就需要说到Promise对象的三种状态了:
Pending待定,未执行resolve()或者reject()时的状态。Fulfilled已完成,执行resolve()后的状态。Rejected拒绝,执行reject()后的状态。
我们来打印一下(这里我把代码包裹在立即执行函数里,放到浏览器DevTools里执行,用VSCodeNode.js执行打印不出resolved状态)
(function(){
const promise = new Promise((resolve,reject)=>{
console.log("Promise");
setTimeout(()=>{
if (Math.random()*100 > 50){//随机数模拟成功率
resolve("success");
}
else {
reject("fail");
}
},500);
});
let it = setInterval(()=>{console.log(promise);},100);
promise.then((value)=>{
console.log("then: ",value);
})
.catch((error)=>{
console.log("catch: ",error);
})
.finally(()=>{
console.log("finally");
setTimeout(()=
clearInterval(it);
},200);
});
}());
第一次运行

第二次执行

Promise对象是传进去的函数参数,这个函数是立即执行的。理解了这一点,我们通常就会把Promise的实例化写到一个函数里,让它作为这个函数的返回值,这样我们调用这个函数时,也就相当于开始执行异步函数了,看代码:
function promiseFun () {
return new Promise((resolve,reject)=>{
setTimeout(()=>{
if (Math.random()*100 >50){//随机数模拟成功率
resolve("success");
}
else {
reject("fail");
}
},500);
});
}
调用
promiseFun().then((value)=>{
console.log("then: ",value);
})
.catch((error)=>{
console.log("catch: ",error);
})
.finally(()=>{
console.log("finally");
});
看到这里你可能对类似这样的链式写法promiseFun().then().catch().finally();有点疑惑,其实这是因为then方法,catch方法都返回一个新的 promise 对象,我们来打印看一下:

thenFun是pending状态的promise对象,1000ms后,是rejected状态的了。
三、来点真香的,异步也能用同步来写
看到这里也许你会觉得这种写法和写普通回调函数好像也没多大区别,这是因为我们举的例子太过简单,假设我们有多个从本地获取文件(或者网络请求)的操作,而每个操作又都依赖上一次操作的结果,这种情况使用使用回调函数就容易陷入回调地狱,而使用Promise结合async/await,完全就是同步的写法了,这个真香啊,直接上代码
function promiseFun1 () {
return new Promise((resolve,reject)=>{
setTimeout(()=>{
if (Math.random()*100 >50){//随机数模拟成功率
resolve("Fun1 success");
}
else {
reject(new Error("error Fun1"));
}
},500);
})
.then((value)=>{return value})
.catch((error)=>{return error.message});
}
function promiseFun2 () {
return new Promise((resolve,reject)=>{
setTimeout(()=>{
if (Math.random()*100 >50){//随机数模拟成功率
resolve("Fun2 success");
}
else {
reject(new Error("error Fun2"));
}
},500);
})
.then((value)=>{return value})
.catch((error)=>{return error.message});
}
function promiseFun3 () {
return new Promise((resolve,reject)=>{
setTimeout(()=>{
if (Math.random()*100 >50){//随机数模拟成功率
resolve("Fun3 success");
}
else {
reject(new Error("error Fun3"));
}
},500);
})
.then((value)=>{return value})
.catch((error)=>{return error.message});
}
(async function (){
console.log("start");
const p1 = await promiseFun1();
console.log("p1:",p1);
const p2 = await promiseFun2();
console.log("p2:",p2);
const p3 = await promiseFun3();
console.log("p3:",p3);
console.log("end");
}());
执行结果:

四、Promise静态方法
Promise还有几个静态方法,Promise.all(iterable),Promise.race(iterable),Promise.reject(reason),Promise.resolve(value);
Promise.all(iterable) 接收一个 Promise 对象的数组,若都通过解决,则在then方法中回调他们的值组成的数组,若其中一个有 reject ,则会被 catch 。看代码:
let promiseFun1 = new Promise((resolve,reject)=>{
resolve("Fun1 success");
setTimeout(()=>{
if (Math.random()*100 > 40){//随机数模拟成功率
resolve("Fun1 success");
}
else {
reject(new Error("error Fun1"));
}
},500);
});
let promiseFun2 = new Promise((resolve,reject)=>{
setTimeout(()=>{
if (Math.random()*100 > 40){//随机数模拟成功率
resolve("Fun2 success");
}
else {
reject(new Error("error Fun2"));
}
},500);
});
let promiseFun3 = new Promise((resolve,reject)=>{
setTimeout(()=>{
if (Math.random()*100 > 40){//随机数模拟成功率
resolve("Fun3 success");
}
else {
reject(new Error("error Fun3"));
}
},500);
});
(async function (){
Promise.all([promiseFun1,promiseFun2,promiseFun3]).then((values)=>{
console.log("values:",values);
}).catch((error)=>{
console.log("error:",error);
});
}());
执行打印:

Promise.race(iterable)是赛跑,看哪个跑的快,只有有其中一个被解决或拒绝,马上返回。
Promise.resolve(value)和Promise.reject()用来直接返回解决或拒绝状态。如
Promise.resolve("ok").then((value)=>{console.log(value)});
执行打印 "ok"。
关于Promise的使用我们暂时告一段落,以后有时间再深入写一篇关于它的实现,和它在EventLoop中的地位。
如果看完觉得对您使用 Promise 有帮助,还有劳点个赞,谢谢啦。
参考文章
Promise - MDN
Master the JavaScript Interview: What is a Promise?
Promise 对象 - ECMAScript 6 入门-阮一峰