1. Promise.all
Promise.all
Promise.all() 方法接收一个 promise 的 iterable 类型(注:Array,Map,Set 都属于 ES6 的 iterable 类型)的输入,并且只返回一个 Promise 实例, 那个输入的所有 promise 的 resolve 回调的结果是一个数组。这个 Promise 的 resolve 回调执行是在所有输入的 promise 的 resolve 回调都结束,或者输入的 iterable 里没有 promise 了的时候。
Promise.myAll = function (promises) {
const values = []; //放置结果
let count = 0; // 记录fullfilled的promise个数
//传入的promises为可迭代对象,不一定为数组
promises = Array.from(promises);
let len = promises.length;
// 需要判断下数组length是否为0,如果为0,则
// forEach不会执行传递的函数,导致promise状态永远为pendding
// 所以要返回一个为fulfilled状态的promise
if (len === 0) {
return Promise.resolve([]);
}
return new Promise((resolve, reject) => {
promises.forEach((p, i) => {
Promise.resolve(p)
.then((res) => {
values[i] = res; // 传递的promsie数组和结果要一一对应
if (++count === len) {
//是否所有的promise都进入fullfilled状态
resolve(values); //返回结果
}
})
.catch((e) => {
reject(e); //如果有一个错误,直接reject并传递 reason
});
});
});
};
2. Promise.race
和Promise.all差不多,但race只返回第一个执行成功或者失败的promise
Promise.myRace = function (iterable) {
// 转换可迭代对象 iterable为 数组
promises = Array.from(iterable);
return new Promise((resolve, reject) => {
promises.forEach((p) => {
Promise.resolve(p)
.then((res) => {
resolve(res);
})
.catch((e) => {
reject(e);
});
});
});
};
3. generatorToAsync(co)
为了解决 Promise 的问题,async、await 在 ES7 中被提了出来,是目前为止最好的解决方案
co是著名程序员 TJ Holowaychuk 于 2013 年 6 月发布的一个小工具,用于 Generator 函数的自动执行。它是用来解决异步操作的开源项目
,也是后来 JavaScript 异步操作的终极解决方案—— async/await 的先驱。
很多人都知道 async 和 await 是 generator 的语法糖,但是不知道其原理,实际上async就是官方实现的co.
下面的generatorToAsync函数可以把一个generator类似转换为于一个async函数,当调用generatorToAsync返回的那个函数时,会自执行
generator.
function generatorToAsync(generatorFn) {
return function () {
const gen = generatorFn.apply(this, arguments);
// 返回一个promise
return new Promise((resolve, reject) => {
//定义step 函数,用于 自执行generator
// ret: key为next时,ret 相当于await返回的值;key为throw,ret为promise执行报错信息
function step(key, ret) {
let generatorResult = null;
// 捕获 gen.next ,gen.throw 执行可能报错,报错的话直接reject掉
try {
generatorResult = gen[key](ret);
} catch (err) {
//报错,return 后面不用再执行了
return reject(err);
}
const { value, done } = generatorResult;
// 若 done 为 true,则说明genertor函数执行完,这时value为genertor的return值
if (done) {
return resolve(value);
} else {
// value 不一定为promise,也可以为不同对象或值,所以用Promise.resolve包裹一下,转为promise对象
Promise.resolve(value).then(
(res) => {
// 正常返回值,继续执行genertor
step("next", res);
},
(err) => {
// gen.throw 强制 抛出错误 , 让generator 函数中的try catch 可以捕获 错误
step("throw", err);
}
);
}
}
step("next");
});
};
}