Promise知识点整理

317 阅读2分钟

JavaScript ES6 难点之一就是 Promise,今天做一下相关知识点整理。如果面试,只需要了解这些就够了,多了也用不上。

一、promise 用途,基本的promise与then

1、Promise 是对象

2、promise对象用于表示异步操作的最终完成或失败,及其结果值。

3、then是挂载在 promise 的原型链上的属性。

4、finally 无论resolve, 还是reject 都会执行

Promise.prototype.then(onFulFilled, onRejected)

5、因为 then 会返回一个新的Promise,所以可以链式调用。

基本的Promise.then 使用

const pTest = function () {
    let randNum = Math.random();
    return new Promise((resolve, reject) => {
    setTimeout( () => {
        randNum > 0.5 ? resolve(randNum) : reject(randNum);
        }, 1000);
    });
}

pTest().then(
    paramResolve => {
        console.log(`this is fulFilled, param is ${paramResolve}`);
    },
    paramReject => {
        console.log(`this is reject, param is ${paramReject}`);
    });

二、promise all

1、用于处理多级联调用下,代码语义不明。输入的迭代类型(iterable)是Array,Map,Set。统一处理所有的resolve和reject。

2、返回情况

resolve返回:

    1. 所有promise的resolve都结束
    2. 没有promise了

reject返回:

    1. 任何一个promise的reject执行,就返回
    2. 输入不合法的promise
    3. reject返回的是第一个reject的信息

3、如何用JS代码实现

function all(iterable) {
    return new Promise((resolve, reject) => {
        let resolveArr = [];  // 所有 promise 的 resolve 参数
        for (let key in iterable) {
            let item = iterable[key];
            // 判断是否为promise
            if (typeof item === 'object' && typeof item.then === 'function') {
                item.then(
                    resolveParam => {
                        resolveArr[key] = resolveParam
                        // 判断是否所有 resolve 都执行了
                        if (resolveArr.length === iterable.length) {
                            resolve(resolveArr);
                        }
                    },
                    // 如果当前item执行reject则整个all结束,返回
                    reject);
            } else {
                resolveArr[key] = item;
            }
        }
    });
}

all([
    Promise.reject(123),  // 1
    Promise.resolve(456),  // 2
    new Promise((resolve, reject) => {
        setTimeout(
            () => {
                resolve(789)
            },
            5000);  // 3
    })
]).then( resolveParam => {
    console.log(resolveParam);
}).catch( err => {
    console.log(err);
})

注释1 处,直接返回 reject,输出 123 结束 注释2 处,如果把1处 注释掉运行,输出 456,789 注释3 处,此处会pending 5秒

三、React 中的 fetch

fetch 比 XmlHttpRequest 效率高。实质也是一个Promise 第一次,header 返回,第二次数据返回。

fetch('/file.txt').then( res => {
    console.log('网络成功');
    console.log(res);

    // let {ok} = res;
    // if(ok){
    //     console.log('接受成功');
    // }else{
    //     console.log('接受失败');
    // }

    // json()使用json格式解析数据,也是返回Promise
    // res.json().then(data => {
    //     console.log(data);
    // }, err => {
    //     console.log('解析失败');
    // });

    return res.json();  //res.json 也是一个Promise
}, err => {
    console.log('网络失败');
}).then(data => {
    console.log(data);
}, err => {
    console.log('解析失败');
});

四、async-await

async-await是基于Promise的语法糖,很多高级程序员不习惯JS 的写法,改造出来的这种写法,目的在于只关注resolve,用catch去处理reject

(async () => {
    try{
        let res = await fetch('/public/exist.txt');
        
        let {ok} = res;
        if(ok){
            console.log('接受成功');
        }else{
            console.log('接受失败');
        }

        // let data = await res.json();
        // let data = await res.arrayBuffer();
        let data = await res.text();
        console.log(data);

    }catch(err){
        console.log('失败');
    }
})();

res能解析哪些格式?

  • .json JSON和数组
  • .arrayBuffer() 二进制的数组
  • .blob 二进制大对象:来源于数据库,不需要解析,用于多媒体文件。
  • .text 文本。