ES6 Promise基础知识总结

2022-10-30 11:27:30

本文主要参考阮一峰的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=newPromise(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=newPromise(function(resolve,reject){resolve('success');})
promise.then(res=>{
	console.log(res);},err=>{
	console.log(err);})

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

let promise=newPromise(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=newPromise(function(resolve,reject){resolve('success');})
prom.then(function(res){
	console.log(res);returnnewPromise((resolve, reject)=>{setTimeout(()=>{resolve(2);},1000);})}).then(res=>{
	console.log(res);})//success 2
2、Promise.prototype.catch()

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

let promise=newPromise(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=newPromise(function(resolve,reject){resolve('success');})
promise.then(res=>{
	console.log(res);returnnewPromise(function(resolve,reject){reject('err1');})}).then(res=>{
	console.log(res)}).catch(err=>{//这里会处理上面所有Promise产生的错误})// success err1

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

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

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

let promise=newPromise(function(resolve,reject){reject(newError('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=newPromise(function(resolve,reject){reject(newError('error'));})
promise.then(res=>{
	console.log(res);}).catch(err=>{
	console.log(err);returnnewPromise((resolve,reject)=>{reject(newError('thisisa 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('thisisa 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=newPromise((resolve, reject)=>{resolve('hello');}).then(res=> res).catch(err=> err);const p2=newPromise((resolve, reject)=>{reject(newError('报错了'));}).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=newPromise((resolve, reject)=>{resolve('hello');})const p2=newPromise((resolve, reject)=>{reject(newError('报错了'));})

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=newPromise((resolve, reject)=>{resolve('hello');})const p2=newPromise((resolve, reject)=>{reject(newError('报错了'));})

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=newPromise((resolve, reject)=>{resolve('hello');})const p2=newPromise((resolve, reject)=>{reject(newError('报错了'));})

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=newPromise((resolve, reject)=>{resolve('hello');})const p2=newPromise((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=newPromise((resolve, reject)=>{reject(newError('报错了'));})const p2=newPromise((resolve, reject)=>{reject(newError('报错了'));})

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');//等价于newPromise(resolve=>resolve('hello'))//hello

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

9、Promise.reject()

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

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

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

  • 作者:三个木马人
  • 原文链接:https://blog.csdn.net/weixin_43299180/article/details/111506615
    更新时间:2022-10-30 11:27:30