IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> JavaScript知识库 -> 手撕Promise之静态API -> 正文阅读

[JavaScript知识库]手撕Promise之静态API

前言

Promise有六个常用的API,包括Promise.resolve()、Promise.reject()、Promise.all()、Promise.any()、Promise.allSelect()以及Promise.race()。前两个API很简单,这里我就过滤掉了,这篇博客主要是实现后面四个API,至于为什么会突然想到去实现这玩意,问就是因为大厂面试会让你现场手撕(裂开)。
这四个API实现的核心思路都差不多,所以我重点只讲述promise.all()的实现过程,后三个API我只给出最终代码。

Promise.all()

API功能

一个API的功能,我们重点关注其参数和返回值,下图是mdn上的介绍:
在这里插入图片描述
提取摘要:参数是个iterable,返回值是个promise。

思路分析

对于iterable,一般不太方便直接处理,所以我们可以使用Array.from将其转换为数组进行处理。然后判断数组是否为空,如果是空数组,直接返回Promise.resolve([])。否则返回一个需要进一步处理的promise,那么进入正题。
显然,我们肯定需要遍历数组并执行每一个promise,但是在外面我们还需要维护一个计数器,每fulfilled一个promise,计数器加1,如果计数器的值等于数组的长度,则将返回的promise执行resolve()。如果有任意一个promise被reject,那么将返回的promise执行reject()。

代码

实现代码:

function promiseAll(arr) {
    // 转换为数组
    const list = Array.from(arr);
    const n = list.length;
    // 特殊情形
    if (n === 0) {
        return Promise.resolve([]);
    }
    return new Promise((resolve, reject) => {
        const res = new Array(n);
        let count = 0;
        for (let i = 0; i < n; i++) {
            Promise.resolve(list[i]).then(r => {
                res[i] = r;
                count++;
                // 全部fulfilled
                if (count === n) {
                    resolve(res);
                }
            }).catch(e => {
                // 任意一个reject
                reject(e);
            });
        }
    })
}

测试代码:

const promise1 = Promise.resolve(3);
const promise2 = 42;
const promise3 = new Promise((resolve, reject) => {
  setTimeout(resolve, 100, 'foo');
});

promiseAll([promise1, promise2, promise3]).then((values) => {
  console.log(values);
});

promiseAll([])
promiseAll([1,2,Promise.resolve(3)])
promiseAll([Promise.resolve(2), 3, Promise.reject(4)]);

对于测试代码,大家可以直接对比原API进行比较。

Promise.any()

实现代码:

function promiseAny(arr) {
    const list = Array.from(arr);
    const n = list.length;
    if (n === 0) {
        return Promise.reject(new AggregateError([]));
    }
    return new Promise((resolve, reject) => {
        const res = new Array(n);
        let count = 0;
        for (let i = 0; i < n; i++) {
            Promise.resolve(list[i]).then(r => {
                resolve(r);
            }).catch(e => {
                res[i] = e;
                count++;
                if (count === n) {
                    reject(new AggregateError(res));
                }
            });
        }
    })
}

测试代码:

const pErr = new Promise((resolve, reject) => {
    reject("总是失败");
});

const pSlow = new Promise((resolve, reject) => {
    setTimeout(resolve, 500, "最终完成");
});

const pFast = new Promise((resolve, reject) => {
    setTimeout(resolve, 100, "很快完成");
});

promiseAny([pErr, pSlow, pFast]).then((value) => {
    console.log(value);
})

Promise.allSelect()

实现代码:

function promiseAllSettled(arr) {
    const list = Array.from(arr);
    const n = list.length;
    if (n === 0) {
        return Promise.resolve([]);
    }
    return new Promise((resolve, reject) => {
        const res = new Array(n);
        let count = 0;
        for (let i = 0; i < n; i++) {
            Promise.resolve(list[i]).then(r => {
                res[i] = {
                    status: "fulfilled",
                    value: r
                };
                count++;
                if (count === n) {
                    resolve(res);
                }
            }).catch(e => {
                res[i] = {
                    status: "rejected",
                    reason: e
                };
                count++;
                if (count === n) {
                    resolve(res);
                }
            });
        }
    })
}

测试代码:

const promise1 = Promise.resolve(3);
const promise2 = new Promise((resolve, reject) => setTimeout(reject, 100, 'foo'));
const promises = [promise1, promise2];

promiseAllSettled(promises).
    then((results) => results.forEach((result) => console.log(result)));

Promise.race()

实现代码:

function promiseRace(arr) {
    const list = Array.from(arr);
    const n = list.length;
    return new Promise((resolve, reject) => {
        // 如果n===0,则永远等待
        for (let i = 0; i < n; i++) {
            Promise.resolve(list[i]).then(r => {
                resolve(r);
            }).catch(e => {
                reject(e);
            });
        }
    })
}

测试代码:

const promise1 = new Promise((resolve, reject) => {
    setTimeout(resolve, 500, 'one');
});

const promise2 = new Promise((resolve, reject) => {
    setTimeout(resolve, 100, 'two');
});

promiseRace([promise1, promise2]).then((value) => {
    console.log(value);
});

结语

到此,本篇有关Promise静态API的讲述已临近尾声,不知大家是否感觉到重复造轮子也有几分乐趣。对于本篇文章的代码如果大家有疑问欢迎评论区留言,如果发现代码有bug也欢迎评论区指出。下期再会。

  JavaScript知识库 最新文章
ES6的相关知识点
react 函数式组件 & react其他一些总结
Vue基础超详细
前端JS也可以连点成线(Vue中运用 AntVG6)
Vue事件处理的基本使用
Vue后台项目的记录 (一)
前后端分离vue跨域,devServer配置proxy代理
TypeScript
初识vuex
vue项目安装包指令收集
上一篇文章      下一篇文章      查看所有文章
加:2021-09-05 10:43:24  更:2021-09-05 10:45:40 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 15:22:31-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码