1、promise介绍
- promise是一个对象,对象和函数的区别就是对象可以保存状态,函数不可以(闭包除外)
- 并未剥夺函数return的能力,因此无需层层传递callback,进行回调获取数据
- 代码风格,容易理解,便于维护
-
2、promise的作用?
主要用于异步计算
- 可以将异步操作队列化,按照期望的顺序执行,返回符合预期的结果
-
3、promise主要解决了哪些问题?
之前处理异步是通过纯粹的回调函数的形式进行处理
- 很容易进入到回调地狱中,剥夺了函数return的能力
- 问题可以解决,但是难以读懂,维护困难
- 稍有不慎就会踏入回调地狱 - 嵌套层次深,不好维护
4、promise使用
promise有三个状态
1、pending[待定]初始状态
2、fulfilled[实现]操作成功
3、rejected[被否决]操作失败
状态一经改变,不会再变,且只有两种改变方式
1、pending变为fulfilled
2、从pending变为rejected。
promise可以使用resolve和reject来改变状态
1、resolve作用是,将Promise对象的状态从“未完成”变为“成功”(即从 pending 变为 fulfilled),在异步操作成功时调用,并将异步操作的结果,作为参数传递出去;
2、reject作用是,将Promise对象的状态从“未完成”变为“失败”(即从 pending 变为 rejected),在异步操作失败时调用,并将异步操作报出的错误,作为参数传递出去。
状态改变后,可以在.then的两个参数中接收状态改变后的值
new Promise(function (resolve, reject) {// 一段耗时的异步操作resolve('成功') // 数据处理完成// reject('失败') // 数据处理出错}).then((res) => {console.log(res)}, // 成功(err) => {console.log(err)} // 失败)
promise还可以分多次顺序执行
在.then中的resolve本质上是新建了一个promise,因为promise状态是不可改变的。
例如分两次顺序执行
new Promise(resolve => {setTimeout(() => {resolve('hello')}, 2000)}).then(val => {console.log(val) // 参数val = 'hello'return new Promise(resolve => { //新建一个promisesetTimeout(() => {resolve('world')}, 2000)})}).then(val => {console.log(val) // 参数val = 'world'})
在任何一个地方生成了一个promise队列之后,我们可以把他作为一个变量传递到其他地方。
let pro = new Promise(resolve => {//此处在调用前便优先执行,等待.then调用setTimeout(() => {resolve('hello world')}, 2000)})setTimeout(() => {console.log('开始执行promise'); 此时promisepro.then(value => {console.log(value) // hello world})}, 2000)
5、错误处理
1、使用.then的第二个参数接收错误
new Promise((resolve,reject) => {setTimeout(() => {// resolve('hello world')reject('error')}, 1000)}).then(value => {console.log(value) // hello world},err =>{console.log(err); //error})
2、抛出错误,使用.catch接收
new Promise(resolve => {setTimeout(() => {resolve('hello world')}, 1000)}).then(value => {console.log(value) // hello worldthrow new Error('test error')}).catch(err => {console.log(err);})
6、Promise.all() 批量执行
Promise.all([p1, p2, p3])用于将多个promise实例,包装成一个新的Promise实例,返回的实例就是普通的promise
- 参数是一个数组,且数组里可以是Promise对象,也可以是别的值,只有Promise会等待状态改变
- 当所有的子Promise都完成,该Promise完成,返回值是全部值的数组
- 有任何一个失败,该Promise失败,返回值是第一个失败的子Promise结果
//切菜function cutUp(){console.log('开始切菜。');var p = new Promise(function(resolve, reject){ //做一些异步操作setTimeout(function(){console.log('切菜完毕!');resolve('切好的菜');}, 1000);});return p;}//烧水function boil(){console.log('开始烧水。');var p = new Promise(function(resolve, reject){ //做一些异步操作setTimeout(function(){console.log('烧水完毕!');resolve('烧好的水');}, 1000);});return p;}Promise.all([cutUp(), boil()]).then((result) => {console.log('准备工作完毕');console.log(result);})//执行结果开始切菜。开始烧水。切菜完毕!烧水完毕!准备工作完毕['切好的菜','烧好的水']
promise.all()会等待全部完成后,所有状态改变后,如果全部为成功状态,把所有成功值返回到fulfilled;如果有失败状态,则返回首个失败状态的值到rejected
//切菜function cutUp(){console.log('开始切菜。');var p = new Promise(function(resolve, reject){ //做一些异步操作setTimeout(function(){console.log('切菜完毕!');reject('切菜失败error');}, 2000);});return p;}//烧水function boil(){console.log('开始烧水。');var p = new Promise(function(resolve, reject){ //做一些异步操作setTimeout(function(){console.log('烧水完毕!');resolve('烧好的水');}, 1000);});return p;}Promise.all([cutUp(), boil()]).then(res => {console.log('准备工作完毕');console.log(res);},err => {console.log('准备失败');console.log(err);})//执行结果开始切菜。开始烧水。烧水完毕!切菜完毕!准备失败切菜失败error
7、promise.race()
Promise.race() 类似于Promise.all() ,区别在于它有任意一个完成就算完成
即promise.race()无论成功或失败状态,都会执行首个执行完成的结果到.then
//切菜function cutUp(){console.log('开始切菜。');var p = new Promise(function(resolve, reject){ //做一些异步操作setTimeout(function(){console.log('切菜完毕!');reject('切菜失败error');}, 2000);});return p;}//烧水function boil(){console.log('开始烧水。');var p = new Promise(function(resolve, reject){ //做一些异步操作setTimeout(function(){console.log('烧水完毕!');resolve('烧好的水');}, 1000);});return p;}Promise.race([cutUp(), boil()]).then(res => {console.log('准备工作完毕');console.log(res);},err => {console.log('准备失败');console.log(err);})//执行结果开始切菜开始烧水烧水完毕!准备工作完毕烧好的水切菜完毕!
8、手写promise
function pro(executor){let self = thisself.status = 'pending'function resolve(value){if(self.status === 'pending'){ //保证状态一旦变更,不能再次修改self.status = 'resolved' //成功状态self.value = value}}function reject(reason){if(self.status === 'pending'){self.status = 'rejected' //失败状态self.reason = reason}}executor(resolve,reject) // 因为会立即执行这个执行器函数}pro.prototype.then = function(onFulfilled,onRejected){let self = thisif(self.status == 'resolved'){onFulfilled(self.value)}if(self.status == 'rejected'){onRejected(self.reason)}}new pro((resolve,reject) => {console.log("a");resolve('b')reject('c')}).then(res=>{console.log(res);},err=>{console.log(err);})console.log('end');
参考文献:
https://www.jianshu.com/p/1b63a13c2701
https://juejin.cn/post/6844903779037347848#heading-1
