笔记:promise

86 阅读2分钟

手写promise

function PromiseN(excute){
    //初始化状态
    this.status = 'pending';
    //状态成功时的值, resolve的参数
    this.value = null;
    //状态失败时的值, reject的参数
    this.reason = null;
    //连续调用(非链式调用)-存储onFulfilled / onRejected 的数组
    this.onFulfilledArray = [];
    this.onRejectedArray = [];
    
    const resolve = (data) => {
        //模拟微任务
        queueMicrotask(() => {
            if(this.status === 'pending'){
                //改变状态和状态对应的值
                this.status = 'fulfilled';
                this.value = data;
                //循环调用储存的onFulfilled方法
                this.onFulfilledArray.forEach(fn => fn());
            }
        })
    };
    const reject = (err) => {
        //模拟微任务
        queueMicrotask(() => {
            if(this.status === 'pending'){
                this.status = 'rejected';
                this.reason = err;
                //循环调用储存的onRejected方法
                this.onRejectedArray.forEach(fn => fn());
            }
        })
    };
     
    try{
        excute(resolve, reject);
    }catch(err){
        throw new Error(err);
    }
}
PromiseN.prototype.then = function(onFulfilled, onRejected) {
    //onFulFilled / onRejected 必须是函数
    onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : (data) => { {return data};
    onRejected = typeof onRejected === 'function' ? onRejected : (err) => { return err};
    
    if(this.status === 'fulfilled'){
        //链式调用then方法, 需要返回promise
        return new PromiseN((resolve, reject) => {
            queueMicrotask(() => {
                try{
                    const result = onFulfilled(this.value);
                    resolve(result);
                }catch(err){
                    reject(err);
                } 
            })
        })
    }
    if(this.status === 'rejected'){
        //链式调用then方法, 需要返回promise
        return new PromiseN((resolve, reject) => {
            queueMicrotask(() => {
                try{
                    const result = onRejected(this.reason);
                    reject(result);
                }catch(err){
                    reject(err);
                }
            })
        })
        
    }
    if(this.status === 'pending'){
        //链式调用then方法, 需要返回promise
        return new PrmomiseN((resolve, reject) => {
            this.onFulfilledArray.push(() => {
                try{
                    const result = onFulfilled(this.value);
                    resolve(result);
                }catch(err){
                    reject(err);
                }
            });
            this.onRejectedArray.push(() => {
                try{
                    const result = onReject(this.reason);
                    reject(result);
                }catch(err){
                    reject(err);
                }
            })
        })
    }
}

如果then中返回值为对象 / 函数 / promise需特殊处理

简单实现Promise.all

function PromiseAll(arr){
    return new Promise((resolve, reject) => {
        const len = arr.length;
        let data = [];
        let count = 0;
        for(let i = 0; i < len; i++){
            Promise.resolve(arr[i]).then(value => {
                data[i] = value;
                //promise全部调用完成后,返回一个结果的数组
                if(++count === len ){
                    resolve(data);
                }
            }).catch(reject)
            //当一个promise失败时, 立即结束返回错误
        }
    })
}

简单实现Promise.race

function PromiseRace(arr){
    return new Promise((resolve, reject) => {
        for(let i = 0; i < arr.length; i++){
            //当一个promise成功或失败时就返回结果, 所有的promise方法依然会执行弹不会对结果做处理
            Promise.resolve(arr[i]).then(resolve, reject);
        }
    })
}

简单实现中断promise

function PromiseWrap(p1){
    let abort;
    const p2 = () =>  new Promise((resolve, reject) => {
        abort = reject;
    })
    //Promise.race当一个promise成功或失败时就返回结果, 通过结束添加的promise来中断当前pending状态的所有promise
    let pw = Promise.race([p1, p2()]);
    //抛出reject方法,主动结束promise
    pw.abort = abort;
    return pw;
}    

生成多个promise

    const promiseArrGenerator = (num) => new Array(num).fill(0).map((item,index) => () => new Promise((resolve, reject) => setTimeout(() => { reolve(index) }, Math.random() * 1000)))
    const promiseArr = promiseArrGenerator(10);

顺序调用

const promiseChain = (promiseArr) => {
    //then返回值是内部的返回值
    promiseArr.reduce((pre,curr) => pre.then(data => {
        //按位取反, 去除初始值
        ~data && console.log(data);
        return curr();
    }),Promise.resolve(-1)).then(data => {
        conosle.log(data);
    })
} 

并发调用并限制并发个数

function promisePipe(promiseArr, num){
    if(promiseArr.length <=  num){
        Promise.all(promiseArr.map(fn => fn())).then(data => console.log(data));
        return;
    }
    let _promiseArr = [...promiseArr];
    //并发调用num个
    for(let i = 0; i < num; i++){
        run(_promiseArr.shift());
    }
    function run(p){
        p().then(data => {
            console.log(data);
            //递归调用,当一个调用完成,就执行下一个
            if(_promiseArr.length) run(_promiseArr.shift());
        });
    }
}