ES6 Promise基础知识总结

本文主要参考阮一峰的ECMAScript 6 入门

一、Promise是什么?

1、含义:Promise 表示异步操作的结果,是异步编程的一种解决方案;它也可以理解成是一个容器,存放着将要执行的事件(异步操作)的结果;从语法上说 Promise 是一个对象,通过它可以获取异步操作的消息。
2、目的:避免函数回调和事件引起的地狱回调问题;Promise 提供了统一的 API,可以使异步操作更加容易。
3、状态:pending(进行中)、fulfilled / resolved(已成功)、rejected(已失败)。
4、特点:Promise 对象的状态不受外界影响;Promise 状态一旦变化就不会再变(从 pending 变为 fulfilled 或从 pending 变为 rejected)。
5、缺点:Promise 一旦创建就会立刻执行,中途无法取消; 不设置回调函数,promise内部抛错不会反应到外部;pending时无法监听到promise进展
6、基本用法:Promise对象是一个构造函数,用来生成Promise实例。

let promise = new Promise(resolve,reject){
    
    
	if(success){
    
    
		resolve(value);
	}else{
    
    
		reject(error);
	}
}

Promise构造函数接受一个函数作为参数,该函数的两个参数分别是resolve和reject。

resolve函数的作用是,将Promise对象的状态从“未完成”变为“已成功”(即从 pending 变为 resolved),在异步操作成功时调用,并将异步操作的结果,作为参数传递出去;
reject函数的作用是,将Promise对象的状态从“未完成”变为“失败”(即从 pending 变为 rejected),在异步操作失败时调用,并将异步操作报出的错误,作为参数传递出去。

二、方法

1、Promise.prototype.then()

then方法是定义在原型对象Promise.prototype上的。它的作用是为 Promise 实例添加状态改变时的回调函数。then方法的第一个参数是resolved状态的回调函数,第二个参数(可选)是rejected状态的回调函数。

let promise = new Promise(function(resolve,reject){
    
    
	resolve('success');
})
promise.then(res=>{
    
    
	console.log(res);
},err=>{
    
    
	console.log(err);
})

then方法返回的是一个新的Promise实例(注意,不是原来那个Promise实例)。因此可以采用链式写法,即then方法后面再调用另一个then方法。

let promise = new Promise(function(resolve,reject){
    
    
	resolve('success');
})
promise.then(res=>{
    
    
	console.log(res);
	return 'second';
}).then(res=>{
    
    
	console.log(res);
})
//success second

上面方法指定两个 then 的回调函数,第一个函数完成后会将返回值作为参数传入第二个函数。

第一个then方法指定的回调函数,返回的是另一个Promise对象。这时,第二个then方法指定的回调函数,就会等待这个新的Promise对象状态发生变化。

const prom= new Promise(function(resolve,reject){
    
    
	resolve('success');
})
prom.then(function(res){
    
    
	console.log(res);
	return new Promise((resolve, reject) => {
    
    
     setTimeout(() => {
    
    
       resolve(2);
     }, 1000);
   })
}).then(res=>{
    
    
	console.log(res);
})
//success 2
2、Promise.prototype.catch()

用于指定发生错误时的回调函数;返回一个 Promise。

let promise = new Promise(function(resolve,reject){
    
    
	reject('error');
})
promise.then(res=>{
    
    
	console.log(res);
}).catch(err=>{
    
    
	console.log(err);
})
// error

上面 Promise 执行状态是 resolved 则会调用 then 指定的回调函数,如果是 rejected 则会调用 catch 指定的回调函数;catch() 方法还可以捕获 then() 方法里面运行的错误。

Promise 对象的错误具有“冒泡性质”,会一直向后面传递,一直到被捕获。所以捕获错误建议使用catch()方法,而不使用then()方法的第二个参数。

let promise = new Promise(function(resolve,reject){
    
    
	resolve('success');
})
promise.then(res=>{
    
    
	console.log(res);
	return new Promise(function(resolve,reject){
    
    
		reject('err1');
	})
}).then(res=>{
    
    
	console.log(res)
}).catch(err=>{
    
    
	//这里会处理上面所有Promise产生的错误
})
// success err1

如果 Promise 状态已经变成resolved,再抛出错误是无效的。

let promise = new Promise(function(resolve,reject){
    
    
	resolve('success');
	reject(new Error('error'));
})
promise.then(res=>{
    
    
	console.log(res);
}).catch(err=>{
    
    
	console.log(err);
})
// success

catch()方法返回的还是一个 Promise 对象,因此后面还可以接着调用then()方法。

let promise = new Promise(function(resolve,reject){
    
    
	reject(new Error('error'));
})
promise.then(res=>{
    
    
	console.log(res);
}).catch(err=>{
    
    
	console.log(err);
	return '2';
}).then(res=>{
    
    
	console.log(res);
})
// Error: error  2

上面的代码,如果没有报错则会跳过 catch() 方法,直接执行下面的 then() 方法。

catch()方法之中,还能再抛出错误。

let promise = new Promise(function(resolve,reject){
    
    
	reject(new Error('error'));
})
promise.then(res=>{
    
    
	console.log(res);
}).catch(err=>{
    
    
	console.log(err);
	return new Promise((resolve,reject)=>{
    
    
		reject(new Error('this is a error'))
	});
}).catch(err=>{
    
    
	console.log(err);
})
// Error: error  Error: this is a error
3、Promise.prototype.finally()

finally() 返回一个 Promise ,方法用于指定不管 Promise 对象最后状态如何,都会执行的操作。该方法是 ES2018 引入标准的。

var promise = Promise.resolve('success')
.then(res=>{
    
    
	console.log(res);
})
.catch(err=>{
    
    
	console.log(err);
})
.finally(()=>{
    
    
	console.log('finally');
})
//success finally

不管 promise 最后的状态,在执行完 then 或 catch 指定的回调函数以后,都会执行 finally 方法指定的回调函数。

在finally之后,还可以继续then,并且会将值原封不动的传递给后面的then;

var promise = Promise.resolve('success')
  .finally(() => {
    
     
    return '1';
  })
  .then(res=> {
    
    
    console.log(res);
  }).catch(err=>{
    
    
	console.log(err);
  });
  //success

finally 对自身返回的 promise 的决议影响有限,它可以将上一个 resolve 改为 reject,也可以将上一个 reject 改为另一个 reject,但不能把上一个 reject 改为 resolve。

var promise = Promise.resolve('success')
  .finally(() => {
    
     
    return Promise.reject('this is a error') 
  })
  .then(res=> {
    
    
    console.log(res)
  }).catch(err=>{
    
    
	console.log(err)
  });
  //this is a error
4、Promise.all()

该方法将多个 Promise 实例包装成一个新的 Promise 实例。

const p = Promise.all([p1, p2, p3]);

Promise.all()方法接收数组作为参数,p1、p2、p3都是Promise实例,如果不是则会调用Promise.resolve()方法将参数转为Promise实例在处理;
对比上面案例:
(1)只有p1、p2、p3的状态都变成resolved,p的状态才会变成resolved,此时p1、p2、p3的返回值组成一个数组,传递给p的回调函数.。
(2)只要p1、p2、p3之中有一个被rejected,p的状态就变成rejected,此时第一个被reject的实例的返回值,会传递给p的回调函数。

const p1 = new Promise((resolve, reject) => {
    
    
  resolve('hello');
})
.then(res => res)
.catch(err => err);

const p2 = new Promise((resolve, reject) => {
    
    
  reject(new Error('报错了'));
})
.then(res => res)
.catch(err => err);

Promise.all([p1, p2])
.then(res => console.log(res))
.catch(err => console.log(err));
// ["hello", Error: 报错了]

上面代码里p1 resolved,p2 rejected,但是由于p2有自己的catch方法,该方法返回的是一个新的Promise实例,p2实际指向这个实例,该实例执行完catch方法之后也会变成 resolved,所以 Promise.all() 两个参数返回的都是 resolved,因此会调用 then 方法指定的回调函数。

const p1 = new Promise((resolve, reject) => {
    
    
  resolve('hello');
})

const p2 = new Promise((resolve, reject) => {
    
    
  reject(new Error('报错了'));
})

Promise.all([p1, p2])
.then(res => console.log(res))
.catch(err => console.log(err));
//Error: 报错了

上面代码p2没有catch方法,所以会走 Promise.all()的catch方法。

5、Promise.race()

跟Promise.all() 一样将多个 Promise 实例,包装成一个新的 Promise 实例。

const p = Promise.race([p1, p2, p3]);

Promise.race()方法接收数组作为参数,p1、p2、p3都是Promise实例,如果不是则会调用Promise.resolve()方法将参数转为Promise实例在处理;
对比上面案例:只要p1、p2、p3之中有一个实例率先改变状态,p的状态就跟着改变。最先改变的 Promise 实例的返回值,就传递给p的回调函数。

const p1 = new Promise((resolve, reject) => {
    
    
  resolve('hello');
})

const p2 = new Promise((resolve, reject) => {
    
    
  reject(new Error('报错了'));
})

Promise.race([p1, p2])
.then(res => console.log(res))
.catch(err => console.log(err));
		// "hello"
6、Promise.allSettled()

该方法接受一组 Promise 实例作为参数,包装成一个新的 Promise 实例。只有等到所有这些参数实例都返回结果,不管是fulfilled还是rejected,包装实例才会结束。该方法由 ES2020 引入。

const p1 = new Promise((resolve, reject) => {
    
    
  resolve('hello');
})

const p2 = new Promise((resolve, reject) => {
    
    
  reject(new Error('报错了'));
})

Promise.allSettled([p1, p2])
.then(res => console.log(res))
//[
//  {status:'fulfilled',value:'hello'},
//	{status:'rejected',reason:Error:报错了}
//]

该方法返回新的 Promise 实例,一旦结束,状态总是fulfilled,不会变成rejected;它会返回一个数组,里面是所有参数最终的运行结果

7、Promise.any()

ES2021 引入了Promise.any()方法。该方法接受一组 Promise 实例作为参数,包装成一个新的 Promise 实例返回。只要参数实例有一个变成 fulfilled 状态,包装实例就会变成 fulfilled 状态(返回的是第一个fulfilled 状态的实例的返回值);如果所有参数实例都变成 rejected 状态,包装实例就会变成rejected状态。

const p1 = new Promise((resolve, reject) => {
    
    
  resolve('hello');
})

const p2 = new Promise((resolve, reject) => {
    
    
  resolve('你好');
})

Promise.any([p2, p1])
.then(res => console.log(res))
.catch(err=>{
    
    console.log(err)})
//hello

Promise.any()跟Promise.race()方法很像,只有一点不同,就是不会因为某个 Promise 变成rejected状态而结束。

Promise.any()抛出的错误,不是一个一般的错误,而是一个 AggregateError 实例。

const p1 = new Promise((resolve, reject) => {
    
    
  reject(new Error('报错了'));
})

const p2 = new Promise((resolve, reject) => {
    
    
  reject(new Error('报错了'));
})

Promise.any([p2, p1])
.then(res => console.log(res))
.catch(err=>{
    
    console.log(err)})
//AggregateError: All promises were rejected
8、Promise.resolve()

有时需要将现有对象转为 Promise 对象,Promise.resolve()方法就起到这个作用。

Promise.resolve('hello');
//等价于
new Promise(resolve => resolve('hello'))
//hello

Promise.resolve()根据参数返回解析后的Promise实例;如果是 Promise 则原封不动返回;参数是thenable对象(带有then方法),会将这个对象转化为Promise,然后立即执行then;参数没有then方法或者是空的,返回一个resolved 状态的 Promise 的对象;

9、Promise.reject()

该方法也会返回一个新的 Promise 实例,该实例的状态为rejected。

Promise.reject('出错了');
//等价于
new Promise(reject=> reject('出错了'))
//出错了

Promise.reject()方法的参数,会原封不动地作为reject的理由,变成后续方法的参数。

猜你喜欢

转载自blog.csdn.net/weixin_43299180/article/details/111506615