思路:首先明白Promise.all的用法
1:promise.all可以接受一个由promise数组作为参数,并且返回一个promise实例,
2:promise.all([a,b,c...]).then方法之后的结果是一个数组,返回的数组是参数中依次执行的返回值
3: 参数中的promise有一个失败则全部失败
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> </body> </html> <script> // 检测传入的是不是promise对象 function isPromise(fun) { return typeof fun.then === 'function' } var p1 = new Promise((reslove, reject) => { setTimeout(() => { reslove('p1') }, 1000) }) var p2 = new Promise((reslove, reject) => { reslove('p2') }) var p3 = 123456; var p4 = function() { return new Promise((reslove, reject) => { reject(new Error('我是一个错误')) }) } // let res1 = isPromise(p1); // console.log(res1); Promise.myAll = function(arr) { return new Promise((reslove, reject) => { let count = 0; let resultArr = []; //存放传入的promise数组中每个promise执行结果的数组 function sortFn(index, value) { // 每次执行+=1,用于计数 count += 1; // resultArr不能直接push到数组中value的值,如果value是个数字,会排在第一位,影响顺序 // 通过传进来的下标去指定位置,这样顺序就是我们想要的,极好! resultArr[index] = value; // 如果都成功了就把结果输出出去 if (count === arr.length) { // console.log(resultArr, "结果"); reslove(resultArr) } } // 遍历传进来的promise数组 for (let i = 0; i < arr.length; i++) { let cur = arr[i]; // 如果数组中当前的这一项是promise,那么就执行这个promise函数 // 并且把执行结果(当前这个promise的索引和结果作为参数传递出去) if (isPromise(cur)) { cur.then(res => { sortFn(i, res); }, reject) //reject就是外层的那个reject,因为只要有一个错误,就抛出 } // 如果不是个promise函数,那么就把当前这一项的索引和其本身传递出去 else { sortFn(i, cur); } } }) } Promise.myAll([p1, p2, p3, p4()]).then(res => { console.log(res); }, err => { console.log(err); }) // 用.catch捕获,也可以向上面那样用then的第二个参数捕获错误 // .catch(err => { // console.log(err); // }) </script>
黄色标记get到思想:
1.为了使循环中的结果添加到newArr新数组中,正常情况下我们会用newArr.push的情况。但是如果传入的数组中不是promise对象,而是一个数字,比如123456,那么最后这个输出这个数组的顺序就变成了数字排在了前面,不符合我们想要的Promise.all的输出顺序。
2.所以我们需要手动保存当前循环中的索引,在上面newArr添加的时候,newArr[index] =value,我们通过存的索引,用数组的下标索引的方式去添加,这样就能保证添加顺序了。
思路:Promise.race的用法:
1.Promise.race()里面也是放了一个数组,数组里面的谁快,谁先执行,执行的结果就是当下这个Promise.race([]).then(res) 这个res结果
2.不论数组里的结果成功还是失败,返回最快的那个结果。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> </body> </html> <script> var p1 = new Promise((reslove, reject) => { setTimeout(() => { reslove('p1') }, 1000) }) var p2 = new Promise((reslove, reject) => { setTimeout(() => { reslove('p2') }, 500) }) var p3 = 123456; var p4 = new Promise((reslove, reject) => { setTimeout(() => { reject(new Error('这是一个错误')) }, 100) }) var p5 = new Promise((reslove, reject) => { reslove('p5') }) function isPromise(fun) { return typeof fun.then === 'function'; } Promise.myRace = function(arr) { return new Promise((reslove, reject) => { for (let i = 0; i < arr.length; i++) { let cur = arr[i]; if (isPromise(cur)) { cur.then(res => { // 谁先执行了,就把结果传出去 reslove(res) }, reject) } else { reslove(cur) } } }) } Promise.myRace([p1, p2, p3, p4, p5]).then(res => { console.log(res); }, err => { console.log(err); }) // 第二种写法:在外面调用catch // .catch(err => { // console.log(err); // }) // Promise.race([p1, p2, p3, p4, p5]).then(res => { // console.log(res, '???'); // }, err => { // console.log(err); // }) </script>
一句话:在传入数组的循环中,执行每一项,谁最快有结果,就直接reslove把结果传递出去。