前言
在JavaScript的世界中,Promise毫无疑问是里程碑式的一个变革,它不仅解决了异步编程中,回调函数嵌套过深的问题,还为Async/Await奠定了基础。
Promise规范最早由CommonJS社区提出,后来成为ES2015(ES6)语言规范,到现在可以说已经成了异步编程的首选方案。
接下来本文将详细讲解Promise的特性和方法,供各位大大们参考,如果文中有不正确的地方,欢迎大家斧正。
话不多说,上才艺!
正文
1、构造函数Promise(excutor)
- excutor:
- Promise构造函数接受一个执行器作为参数(excutor,其实就是一个回调函数),在Promise构造函数执行时,会立即执行传入的excutor。
- excutor函数被调用时,会传入resolve, reject两个函数作为参数;当resolve函数被调用,Promise状态变更为fulfilled(完成);当reject函数被调用,Promise状态变更为rejected(失败)
- 如果excutor内部抛出异常,Promise状态将直接变更为rejected,错误对象将作为结果返回。
const p = new Promise((resolve, reject) => {
console.log("excutor函数会被立即执行");
resolve("状态变更为:fulfilled");
// reject("状态变更为:rejected");
// throw new Error('报错,Promise状态将直接变更为rejected')
});
2、状态
Promise一共有3中状态:
3、实例方法
- then(onFulfilled, onRejected)
- 作用:
- 为Promise注册onFulfilled和onRejected回调
- 返回新的promise,实现链式调用
- 新的promise将以回调函数返回值来resolve
- 特性:
- then方法本身会自动返回一个新的Promise对象,当然也可以手动在任意(onFulfilled或者onRejected)回调函数中返回一个Promise对象
const p = new Promise((resolve, reject) => {
console.log("excutor函数会被立即执行");
resolve("状态变更为:fulfilled");
});
// then方法本身会返回一个promise
p.then()
.then()
.then((res) => {
console.log(res); //输出:状态变更为:fulfilled
});
// then方法通过回调函数可以返回promise
p.then(
(res) => {
return new Promise((resolve, reject) => {
resolve("onFulfilled中返回的Promise");
});
},
(reason) => {
return new Promise((resolve, reject) => {
resolve("onRejected回调中也可以返回Promise");
});
}
).then((res) => {
console.log(res);
});
- then方法可以通过返回的Promise对象,实现链式调用
- 如果回调函数返回的是普通值,那么将会在下一个then中作为回调函数参数被接收
- 如果回调函数返回的是一个Promise, 下一个then方法将会等待这个Promise执行结束,并接收Promise的执行结果
const p2 = new Promise((resolve, reject) => {
console.log("excutor函数会被立即执行");
resolve("状态变更为:fulfilled");
});
p2.then(res => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve('promise执行完毕')
}, 1000);
})
}).then(res => {
console.log(res)//等待1秒钟,输出:promise执行完毕
})
- 如果没有传入回调函数,Promise将自动为then方法注册回调函数,并在回调函数中将接收到的值返回,传递给下一个then,实现值的穿透。
没有给then注册回调,发生值穿透
const p3 = new Promise((resolve, reject) => {
resolve(1);
});
p3.then(2).then(4).then(console.log); //1
- then方法中不允许将本身返回的promise对象作为返回值
const p4 = p3.then(res => {
// 不允许,将会报错
// TypeError: Chaining cycle detected for promise #<Promise>
return p4
})
- catch(onRejected)
- 作用
- 给Promise添加onRejected回调
- 特性
- 返回一个新的Promise
- 新的Promise将以回调函数返回值来resolve
const promise = new Promise((resolve, reject) => {
reject(100);
});
promise
.catch((reason) => {
console.log(reason); //100
return 200; //catch函数返回值将作为新Promise的resolve结果
})
.then((res) => {
// 新Promise执行结果
console.log(res); //200
});
- finally(finallyCallback)
- 作用
- 给Promise添加一个事件处理回调函数
- 特性
- 无论成功还是失败,都会调用传入的finallyCallback
- finallyCallback会返回一个新的Promise
- finallyCallback内部不能获取到Promise执行结果
const promise = new Promise((resolve, reject) => {
resolve(100);
});
promise
.finally((res) => {
console.log("finally回调函数无论成功或者失败,始终会被执行");
// finally回调函数内获取不到promise执行结果
console.log(res);
})
.then((res) => {
// finally回调函数返回一个新的promise,实现链式调用
console.log(res);
});
4、静态方法
- Promise.all(promiseArray)
- 作用:
- 接受一个数组作为参数,将执行结果以数组形式顺序返回
- 并发执行数组中的promise对象
- 特性:
- 接受一个数组作为参数,数组元素可以是普通值,也可以是promise对象
- 执行结果以数组形式返回,数组中元素跟传入的promiseArray一一对应
- 如果传入的数组中元素是普通值,直接原样将对应值放入结果数组中
- 如果传入的数组中元素是promise对象,将并发执行对应的Promise对象,并等待执行结束,返回结果
const promise1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve("p1");
}, 2000);
});
const promise2 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve("p2");
}, 1000);
});
const promiseAll = Promise.all([1, 2, promise1, 3, 4, promise2, 5]);
promiseAll.then((res) => {
//并发执行promise
//执行结果与传入的数组一一对应
//会等待所有任务执行完毕之后统一返回结果
console.log(res); //[1,2,"p1",3,4,"p2",5]
});
- 如果传入的数组中某一项执行失败,那么Promise将会执行失败
const promise1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve("p1");
}, 2000);
});
const promise2 = new Promise((resolve, reject) => {
setTimeout(() => {
reject('我这该死的温柔,居然执行失败了')
}, 1000);
});
const promiseAll = Promise.all([1, 2, promise1, 3, 4, promise2, 5]);
promiseAll.then((res) => {
// 任何一个任务执行失败 ,整个promise将执行失败
console.log(res);
}).catch(e => {
//任何一个任务失败,将导致整个Promise执行失败
console.log('fail',e)
});
- Promise.allSettled(promiseArray)
非正式版,目前处于stage4阶段,尚未完全被浏览器支持
- 作用:
- 同Promise.all
- 特性:
- 等待数组中所有任务执行完毕,返回一个数组
- 无论成功还是失败,都会有返回结果
- 其它同Promise.all
const promise1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve("p1");
}, 2000);
});
const promise2 = new Promise((resolve, reject) => {
setTimeout(() => {
reject("我这该死的温柔,居然执行失败了");
}, 1000);
});
const promiseAll = Promise.allSettled([1, 2, promise1, 3, 4, promise2, 5]);
promiseAll
.then((res) => {
/**
Promise.allSettled执行结果
[
{ status: 'fulfilled', value: 1 },
{ status: 'fulfilled', value: 2 },
{ status: 'fulfilled', value: 'p1' },
{ status: 'fulfilled', value: 3 },
{ status: 'fulfilled', value: 4 },
{ status: 'rejected', reason: '我这该死的温柔,居然执行失败了' },
{ status: 'fulfilled', value: 5 }
]
*/
console.log(res);
})
.catch((e) => {
console.log("fail", e);
});
- Promise.race(promiseArray)
- 作用
- 接受一个数组, 并发执行数组中的任务
- 谁执行块,就返回谁的结果,无论成功还是失败
- 一般用来做网络超时功能
const promise1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve("p1");
}, 2000);
});
const promise2 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve("p2");
}, 1000);
});
const promise3 = new Promise((resolve, reject) => {
// 假设500毫秒后网络超时
setTimeout(() => {
reject("超时了");
}, 500);
});
const promiseRace = Promise.race([promise1, promise2, promise3]);
promiseRace
.then((res) => {
console.log(res);
})
.catch((e) => {
// 谁执行块,就返回谁
console.log("fail", e);
});
- Promise.reject(reason)
- 作用:
- 返回一个状态为失败的Promise,并将失败信息传递给对应的处理方法
Promise.reject("rejected")
.then((res) => {
console.log('value', res);
})
.catch((reason) => {
// reason rejected
console.log('reason', reason);
});
- Promise.resolve(value)
- 作用:
- 接受一个值,返回一个Promise
- 特性:
- 如果value是一个普通值,则将普通值作为新Promise的resolve结果
- 如果value是一个Promise,则将value原样返回
Promise.resolve(100).then((res) => {
console.log(res); //100
});
const promise = new Promise((resolve, reject) => {
reject(200);
});
promise
.then((res) => {
console.log(res); //200
});
总结
至此,Promise的用法就总结完啦,感谢大家的阅读,希望对大家有所帮助。有什么想法快去评论区说出来吧,我们一起探讨,共同进步。
在了解完Promise使用方法之后,下一篇文章,我将通过手写源码的方式,进一步讲解Promise的核心原理。