JS 简易模拟Promise.all
先来看下MDN关于该方法的定义:
Promise.all() 方法接收一个promise的iterable类型的入参,如果输入的所有promise都被resolve(fuifulled),那么将返回一个Promise<Array>实例;如果其中有任何一个promise被reject(rejected),那么将会返回该条错误信息。
Code:
/**
* 模拟Promise.all方法
*/
Promise._all = (function() {
/**
* 模拟实现
* @param {Promise[]} promises
* @return {Promise}
*/
var miniPromiseAll = function(promises) {
if (promises[Symbol.iterator] === undefined) {
return Promise.reject('TypeError: 参数不合法!');
}
// 统一设定将promises参数的数据类型规范为数组
promises = Array.prototype.slice.call(promises);
// promises = [...promises];
/**
* 异步处理完成后的结果列表
* @type {Promise[]}
*/
var fulFilledList = [];
/**
* promises数组的长度
* @type {number}
*/
var n = promises.length;
/**
* 初始化时的自定义处理函数
* @param {Function} resolveFn
* @param {Function} rejectFn
*/
var executor = function(resolveFn, rejectFn) {
// 已兑现的数量
var cnt = 0;
for (var i = 0; i < n; i++) {
(function(idx) {
Promise.resolve(promises[idx])
.then(function(res) {
// 根据当前的index索引进行填入,确保与原promises数组的次序相同
fulFilledList[idx] = res;
// 待所有数组元素都兑现后
if (++cnt === n) {
resolveFn(fulFilledList);
}
})
.catch(rejectFn);
})(i);
}
};
return new Promise(executor);
};
return miniPromiseAll;
})();
//// 测试用例
var promises = [
// Promise item 1:
Promise.resolve('a'),
// Promise item 2:
new Promise(function(resolve) {
window.setTimeout(function() {
resolve('b');
}, 600);
}),
// Promise item 3(非Promise对象):
'c',
// Promise item 4:
new Promise(function(resolve) {
window.setTimeout(function() {
resolve('d');
}, 100);
}),
];
/**
* 测试结果的log函数
* @param {*[]} result
*/
var testLog = function(result) {
console.log('Mini Promise.all result: ', result);
};
Promise._all(promises)
.then(testLog)
.catch(console.warn);
_模拟实现(2022年时的一段代码,废弃但保留):
/** * 模拟Promise.all * @param {Array} promises - Promise数组 * @return {Promise} */ Promise._all = function(promises) { // 如果传入的不是可迭代对象 if (promises[Symbol.iterator] === undefined) { return Promise.reject('"promises" is not iterable (cannot read property Symbol(Symbol.iterator))'); } // 异步的完成结果容器 const fulfilledList = []; return new Promise((resolve, reject) => { // 使用for...of迭代promises for (const p of promises) { // 对promises数组中的元素进行Promise包裹,保证其为promise对象 Promise.resolve(p) .then(res => { // 异步状态顺利完成后,将结果推入容器 fulfilledList.push(res); // 如果元素数量与promises的容量相等就可以返回了 if (fulfilledList.length === promises.length) { resolve(fulfilledList); } }) // 任何一个元素出现失败状态则reject .catch(err => reject(err)); } }); }; //// 测试代码 ---- var p1 = 1; var p2 = new Promise(resolve => { window.setTimeout(() => { resolve('2'); }, 400); }); var p3 = Promise.resolve(3); Promise._all([p1, p2, p3]) .then(ans => { console.log(ans); }) .catch(err => { console.warn(err); });
end
分类:
JavaScript
标签:
JavaScript
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 【杂谈】分布式事务——高大上的无用知识?