IT博客汇
  • 首页
  • 精华
  • 技术
  • 设计
  • 资讯
  • 扯淡
  • 权利声明
  • 登录 注册

    面试官桀桀一笑:请手写一个Promise.all(判断是不是Promise、js抛出错误)

    水冗水孚发表于 2024-05-09 10:20:09
    love 0

    前言

    • 本文如标题,回顾三个知识点
    • 判断是不是Promise
    • js抛出错误的类型
    • 手写Promise.all

    判断是不是Promise

    方式一 Object.prototype.toString.call

    代码如下:

    // p存在,且对象原型上是Promise
    function isPromise(p) {
        return p && Object.prototype.toString.call(p) === "[object Promise]";
    }

    方式二 Promise有.then方法,以此为依据

    代码如下:

    // 有值,且值是对象或函数,在一个也要有.then的函数方法
    function isPromise(val) {
        return (
            val &&
            (typeof val === 'object' || typeof val === 'function') &&
            typeof val.then === 'function'
        );
    }

    二者对比

    • 方式二比方式一更为精准强大(推荐)
    • 对于规范化的Promise(就是JavaScript自带的Promise)
    • 二者判断检测结果能力都一样
    • 但是对于一些特定的Promise可能不太准确
    • 比如:特定库的Promise(Tiny Promise)、或者自己继承Promise去操作什么的,可能不太够用
    • 不过正常来说也够用了

    js如何抛出错误?

    • 在js中抛错是通过throw语句,进一步来说,又可以分为:
    • 直接抛
    • 进阶抛

    直接抛错误

    throw语句后面抛什么都行,比如:

        // 抛出各种数据类型
        throw '报错了' 
    
        throw 404
    
        throw false
    
        throw null
    
        throw undefined
    
        throw {}
    
        throw () => {}
    
        throw []

    一般来说,抛出字符串比较多一些,不会抛出各种其他的数据类型

    进阶抛错误

    • 如果想要进一步明确错误的类型
    • 可以使用js自带的Error相关构造函数
    • 一般常见的有4个如下:
    // 常见的4种进阶错误区分
    throw new Error('普通错误') // 抛出普通错误(用的多一些)
    
    throw new SyntaxError('语法错误') // 抛出语法错误
    
    throw new ReferenceError('引用错误') // 抛出引用错误
    
    throw new RangeError('范围错误') // 抛出范围错误

    工作中我们根据具体的情况和需求,选择合适的方式来抛出错误能处理异常更加“优雅”

    手写一个Promise.all

    复制粘贴即用,注释代码:

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
        <script src="https://cdn.bootcdn.net/ajax/libs/axios/1.3.0/axios.js"></script>
    </head>
    
    <body>
        <script>
            // 判断是不是Promise
            function isPromise(p) {
                return p && Object.prototype.toString.call(p) === "[object Promise]";
            }
    
            function myPromiseAll(promises) {
                return new Promise((resolve, reject) => {
                    if (!Array.isArray(promises)) {
                        throw new TypeError('接收的必须是数组,不是数组抛错');
                    }
                    if (promises.length === 0) {
                        throw new Error('接收的数组不能为空,空数组也抛错');
                    }
                    // Promise.all接收数组,最终也返回数组,result存起来用于返回
                    const result = [];
                    // 已经完成的数量,初始为0
                    let doneNum = 0;
                    // 数组循环执行
                    promises.forEach((promise, index) => {
                        if (!isPromise(promise)) { throw new TypeError('接收的数组中的每一项都必须要是Promise') }
                        promise
                            .then((val) => {
                                result[index] = val; // 顺序存值
                                // result.push(val); // 非顺序存值
                                doneNum = doneNum + 1; // 已完成数量+1
                                if (doneNum === promises.length) { resolve(result) } // 任务全部完成,resolve出去
                            })
                            .catch((err) => {
                                // 只要有一个Promise失败,立刻拒绝返回Promise
                                reject(err);
                            })
                    });
                });
            }
    
            const p1 = function () {
                return new Promise(async (resolve, reject) => {
                    let res = await axios.get('http://ashuai.work/api/getIdName?id=1')
                    resolve(res)
                })
            }
            const p2 = function () {
                return new Promise(async (resolve, reject) => {
                    let res = await axios.get('http://ashuai.work/api/getIdName?id=2')
                    resolve(res)
                })
            }
            const p3 = function () {
                return new Promise(async (resolve, reject) => {
                    let res = await axios.get('http://ashuai.work/api/getIdName?id=3')
                    resolve(res)
                })
            }
    
            myPromiseAll([p1(), p2(), p3()])
                .then((values) => { console.log(values) })
                .catch((error) => { console.error(error) })
    
        </script>
    </body>
    
    </html>
    手写Promise... 未完待续...


沪ICP备19023445号-2号
友情链接