Promise.all()、Promise.allSettled()原理及实现

Promise.all()

原理简述:

MDN:

  • Promise.all() 方法接收一个promise的iterable类型(注:Array,Map,Set都属于ES6的iterable类型)的输入。
  • 并且只返回一个Promise实例, 输入的所有promise的resolve回调的结果是一个数组。
  • Promise的resolve回调执行是在所有输入的promise的resolve回调都结束,或者输入的iterable里没有promise了的时候。
  • 它的reject回调执行是,只要任何一个输入的promise的reject回调执行或者输入不合法的promise就会立即抛出错误,并且reject的是第一个抛出的错误信息。
简单实现:

为了测试结果更直观一些,这里使用真实接口(来自我的博客:kayrain.cn

function fetchAction(url) {
	return new Promise((resolve, rejected) => {
		const xhr = new XMLHttpRequest();
		xhr.onreadystatechange = function() {
			if (xhr.readyState != 4) return;
			if (xhr.readyState == 4 && xhr.status == 200) {
				resolve(JSON.parse(xhr.responseText))
			} else {
				rejected('网络错误')
			}
		}
		xhr.open('get', url);
		xhr.send(null);
	})
}

const p1 = fetchAction("https://www.kayrain.cn/api/post/list?pageNo=1&pageSize=10&title=&tag=")
const p2 = fetchAction("https://www.kayrain.cn/api/post/list?pageNo=1&pageSize=10&title=&tag=")
// 将p3定义为错误请求
const p3 = fetchAction("https://www.kayrain.cn/api/post/list")

实现all():

Promise.newAll = function(promises) {
	return new Promise((resolve, reject) => {
		let list = [],
			len = promises.length,
			count = len;
		for (let i = 0; i < len; i++) {
			promises[i].then(res => {
				list[i] = res;
				if (--count === 0) {
					resolve(list)
				}
			}, error => {
				reject(error)
			})
		}
	})
} 
Promise.newAll([p1, p2, p3]).then(res => console.log('Promise.all:', res))

运行代码,由于有错误请求出现,所以打印结果为:

在这里插入图片描述

将p3改为正确请求,全部resolve后的结果为:

在这里插入图片描述

Promise.allSettled()

原理简述:

MDN:

  • Promise.allSettled()方法返回一个在所有给定的promise都已经fulfilled或rejected后的promise,并带有一个对象数组,每个对象表示对应的promise结果。
  • 当有多个彼此不依赖的异步任务成功完成时,或者总是想知道每个promise的结果时,通常使用它。
    相比之下,Promise.all() 更适合彼此相互依赖或者在其中任何一个reject时立即结束。
  • 简言之Promise.allSettled 只关心所有 promise 是不是都被 settle 了,不管其是 rejected状态的 promise,还是非 rejected状态(即fulfilled)的 promise, 都可以拿到它的最终状态并对其进行处理。
简单实现
Promise.newAllSettled = function(promises) {
	return new Promise(resolve => {
		let list = [],
			len = promises.length,
			count = len;
		for (let i = 0; i < len; i++) {
			promises[i].then(res => {
				list[i] = {
					status: 'fulfilled',
					value: res
				};
			}, error => {
				list[i] = {
					status: 'rejected',
					reason: error
				};
			}).finally(() => {
				// 循环完成后再resolve,防止出现空属性
				if (--count === 0) resolve(list);
			})
		}
	})
}

Promise.newAllSettled([p1, p2, p3]).then(res => console.log('Promise.allSettled:', res))

运行代码,打印结果为:

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Promise.all和Promise.allSettled是两种不同的Promise方法,它们在使用场景和返回结果上有所不同。 1. Promise.all: - 使用场景:当需要等待多个Promise对象都完成后再执行后续操作时,可以使用Promise.all。 - 返回结果:返回一个新的Promise对象,Promise对象在所有给定的Promise对象都已经fulfilled后才会fulfilled,如果其中任何一个Promise对象被rejected,则返回的Promise对象会立即被rejected。 - 示例代码: ```javascript const promise1 = Promise.resolve(1); const promise2 = Promise.resolve(2); const promise3 = Promise.resolve(3); Promise.all([promise1, promise2, promise3]) .then(values => { console.log(values); // 输出:[1, 2, 3] }) .catch(error => { console.log(error); // 如果有任何一个Promise对象被rejected,则会执行这里的代码 }); ``` 2. Promise.allSettled: - 使用场景:当需要等待多个Promise对象都完成后,无论是fulfilled还是rejected,都需要获取每个Promise对象的结果时,可以使用Promise.allSettled。 - 返回结果:返回一个新的Promise对象,该Promise对象在所有给定的Promise对象都已经fulfilled或rejected后才会fulfilled,返回的Promise对象带有一个对象数组,每个对象表示对应的Promise对象的结果,包括状态(fulfilled或rejected)和值。 - 示例代码: ```javascript const apiOne = function(id) { return new Promise((resolve, reject) => { resolve({ result: true, text: 1 }); }); }; const apiTwo = function(id) { return new Promise((resolve, reject) => { reject({ result: true, text: 2 }); }); }; Promise.allSettled([apiOne('one'), apiTwo('two')]) .then(results => { console.log(results); /* 输出: [ { status: 'fulfilled', value: { result: true, text: 1 } }, { status: 'rejected', reason: { result: true, text: 2 } } ] */ }) .catch(error => { console.log(error); }); ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值