美文网首页
你不知道的JS(中卷)笔记——Promise

你不知道的JS(中卷)笔记——Promise

作者: 李牧敲代码 | 来源:发表于2020-03-31 20:30 被阅读0次

    【前言】

    对于Promise这块几乎是前端面试必问的模块了。《你不知道的JS》里对Promise的总结感觉还没有阮一峰《ES6 标准入门(第3版)》总结的好,建议大家可以看阮一峰的总结。
    Promise是为了解决“回调地狱”的问题的。Promise简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。从语法上说,Promise 是一个对象,从它可以获取异步操作的消息。Promise 提供统一的 API,各种异步操作都可以用同样的方法进行处理。

    本文目录:

    1. Promise的特点
    2. Promise.prototype.then
    3. Promise.protype.catch
    4. Promise.protype.finally
    5. Promise.all
    6. Promise.race
    7. Promise.allSettled
    8. Promise.resolve
    9. Promise.reject
    10. 自己实现Promise对象

    Promise 的特点:

    1. 无法取消,
    2. 包含resolve,pending,reject3个状态
    3. 通过构造器(new Promise)的形式会直接执行参数里的异步操作。

    Promise.prototype.then

    接受2个参数,第一个参数是处理“成功”的函数,第二个参数是处理“失败”的函数,返回一个Promise对象(既可以链式调用接着处理)

    
    
    let p1 = new Promise((resolve, reject) => {
        resolve('success')
    })
    
    p1.then((v) => {
        console.log(v)
        return Promise.resolve(123)//给下一个then的函数提供入参
    },
    (err) => {
        console.log(err)
    }
    ).then((v) => {
        console.log(v)
    })
    

    Promise,protype.catch

    这个方法是用于捕获错误的,和promise.prototype.then第二个函数捕获错误的区别是这样写更加简洁清晰(注意:如果之前没有捕获过,catch和then都能捕获之前第一个发生错误的地方)

    如果之前没发生错误可以通过then进行链式调用:then().then()... :

    let p1 = new Promise((resovle, reject) => {
        resovle('success1')
        // reject('err1');
    }).then((v) => {
        console.log('v1', v)
        return new Promise((resolve, reject) => {
            resolve('success2')
        })
    }, (err) => {
    
    }).then((v) => {
        console.log('v2', v)//如果;之前没发生错误可以通过then进行链式调用then().then()
    },(err) => {
    
    })
    
    //v1 success1
    //v2 success2
    

    中途发生错误,如果是紧挨着的上个promise中发生错误,那么可以通过then的第二个参数函数捕获也可以通过catch捕获,但是catch写起来更加清晰:

    let p1 = new Promise((resovle, reject) => {
        reject('err1');
    }).then((v) => {
        return new Promise( (resovle, reject) => {
            reject('err2')
        })
    }).then(v => {
    
    }, err => {
        console.log('err', err)
    })
    
    //等同于:
    
    let p1 = new Promise((resovle, reject) => {
        reject('err1');
    }).then((v) => {
        return new Promise( (resovle, reject) => {
            reject('err2')
        })
    }).catch((err) => {
        console.log('err', err)
    })
    
    

    promise.protype.finally

    简单一句话就是Promise不管之前什么情况,最后都会执行的地方。

    let p1 = new Promise((resovle, reject) => {
        reject('err1');
    }).then((v) => {
        return new Promise( (resovle, reject) => {
            reject('err2')
        })
    }).catch((err) => {
        console.log('err', err)
    }).finally(()=> {
       //.....
    })
    

    promise.all

    const p1 = new Promise((resolve, reject) => {
        resolve('p1')
    })
    const p2 = new Promise((resolve, reject) => {
        // resolve('p2')
        reject('p2')
    })
    const p3 = new Promise((resolve, reject) => {
        resolve('p3')
    })
    
    
    Promise.all([p1,p2,p3]).then(([v1, v2, v3] = v) => {
        
        // const [v1, v2, v3] = v;
        console.log(v1, v2, v3)
    }).catch((err) => {
        console.log('err', err)
    } )
    
    

    以上面代码为例,

    1. Promise.all 接受一个具有Iterator接口的对象作为参数。
    2. 如果元素不是promise对象则会通过Promise.resolve转化成Promise对象,
      3, 返回一个新的promise对象.
    3. 只有当p1, p2, p3都resolve才会进入then的第一个回调函数里,参数是所有resove的值组成的数组。否则第一个发生的错误被catch捕获(或者then第二个参数捕获,无论哪种捕获前提是p1,p2,p3自身没有去捕获错误)。

    Promise.race

    和Promise.all一样,不同点是:

    1. 第一个值是resolve的,则会进入then的第一个回调函数里。否则被catch捕获
      其中一个用途就是设置Promise超时时间:
    const p1 = new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve('p1')
        }, 1000)
        // resolve('p1')
    })
    const p2 = new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve('p2')
        }, 2000)
        // resolve('p2')
        // reject('p2')
    })
    const p3 = new Promise((resolve, reject) => {
        setTimeout(() => {
            reject('p3')
        }, 3000)
        // resolve('p3')
    })
    
    
    
    const myTimeOut = new Promise((resolve, reject) => {
        setTimeout(() => {
    
            reject('超时了')
        }, 500)
    })
    
    Promise.race([p1,p2,p3, myTimeOut]).then((v) => {
        console.log(v)
        // console.log('rlt', v1, v2, v3)
    }).catch((err) => {
        console.log('err', err)
    } )
    
    

    Promise.allSettled

    这个API主要是你不all的不足的,和all一样,区别是:

    1. 其结果总是fullfiled
    2. 无论每个promise返回的结果如何,allSettled 都会等待所有结果返回,再进入then执行(想设置超时则给具体的promise设置),其结果是一个包含直接执行结果的数组:
    const p1 = new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve('p1')
        }, 1000)
    })
    const p2 = new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve('p2')
        }, 2000)
    
    })
    const p3 = new Promise((resolve, reject) => {
        setTimeout(() => {
            reject('p3')
        }, 3000)
        // resolve('p3')
    })
    
    Promise.allSettled([p1,p2,p3]).then((v) => {
        console.log(v)
    }).catch((err) => {
        console.log('err', err)
    } )
    
    // [
    //     { status: 'fulfilled', value: 'p1' },
    //     { status: 'fulfilled', value: 'p2' },
    //     { status: 'rejected', reason: 'p3' }
    // ]
    

    Promise.resolve

    该方法接受一个参数,返回一个promised对象。根据传入参数的不同,有如下是区别:

    1. 如果传入的是个一promise对象,则原封不动的返回传入的promise对象。
    2. 如果传入的是"thenable"——即含有then方法的对象。则会将该对象转化为Promsie对象并且立即执行then方法
    3. 如果传入的是不是“thenable”或者不是对象,则会返回一个新的Promise对象,状态为fullfileld,并且在then里可以获取传入的参数。(可以用于转化成promise对象)
    4. 如果为传入任何值,则生成一个新的Promise对象 ,状态为fullfileld。

    Promise.reject

    其他和Promise.resolve一样,不同点是reject的参数会看原封不动的作为后面错误捕获的理由.

    自己实现Promise对象

    Promise有很多规范,我们按照其规范在结合文章开头阮一峰对Promise的总结一步一步实现即可,ES6用的是Promises/A+规范

    Promise 有四个基础特性,所有API都可以在这四个基础特性上完善:

    1. 构造函数的实现,就是通过new 创建一个Promise对象
    2. Promise.prototype.then的实现
    3. resolve的实现
    4. reject的实现
      我们先逐步实现上述4个特性,最后会贴上所有API的完整代码:

    理下构造函数大致要做的7件事情:

    1. 定义resolve方法
    2. 定义reject方法
    3. 定下promise的状态
    4. 定义下promise的回调函数集(包括fullfilled和rejected)
    5. 执行传入的那个函数参数
    6. 非promise类型转promise类型
    7. 一些错误处理
    let myPromise = (function () {
        stateArr = ['fullfilled', 'rejected', 'pending'];//全局中定义下状态集合,方便取用
    
        function Promise(resolver) {//构造函数
            let self = this;
            self.state = 'pending';// 初始化状态值
            self.callbacks = [];//存放resolve函数集合和reject函数集合,比如同一个promise多次调用then就会出现累加的情况
            if (typeof resolver !== 'function') {// 构造函数传入的resolver必须是函数
                throw new TypeError(`Promise resolver ${resolver} is not a function`);
            } else {
                if (!!!(this instanceof Promise)) {//不是promise类型的转化为promise类型
                    console.log('创建Promise成功')
                    return new Promise(resolver)
                }
            }
    
    
            function resolve(value) {
                setTimeout(() => {
                    if (self.state !== stateArr[2]) {//一旦状态改变,就不会再变
                        return
                    } else {
                        //改变状态
                        self.state = stateArr[0];
                        //存储resolve的值
                        self.data = value;
                        self.callbacks.forEach((item, index, arr) => {
                            try {
                                item.onResolved(value);
                            } catch (e) {
                                reject(e)
                            }
                        })
                    }
                })
            }
            function reject(reason) {
                setTimeout(() => {
                    if (self.state !== stateArr[2]) {//一旦状态改变,就不会再变
                        return
                    } else {
                        //改变状态
                        self.state = stateArr[1];
                        self.data = reason;
                        self.callbacks.forEach((item, index, arr) => {
                            try {
                                item.onRjected(reason);
                            } catch (e) {
                                reject(e)
                            }
                        })
                    }
                })
            }
    
            try {
                resolver(resolve, reject);
            } catch (e) {
                reject(e)
            }
        }
    })()
    
    理下Promise.prototype.then要做的几件事情
    1. 返回新的promise
    2. 将onResolved和onRrejected添加到回调函数集里
    3. 处理返回同一个promise的情况
    4. 处理返回“thenable”的情况
       function resolvePromise(promise, x, resolve, reject) {//处理resolve的函数
           let thenCalledOrThrow = false;
           if (promise === x){ //不能返回同一个promise
               throw reject(new TypeError(`Chaining cycle detected for promise!`))
           } else {
               if ((x !== null) && typeof x === 'object' || typeof x === 'function') {//处理thenable
                   try {
                       let then = x.then;
                       if (typeof then === 'function') {
                           then.call(x, function rs(rlt) {
                               if (thenCalledOrThrow) {
                                   return
                               } else {
                                   thenCalledOrThrow = true;
                                   resolvePromise(promise, rlt, resolve, reject)
                               }
                           }, function rj(reason) {
                               if (thenCalledOrThrow) {
                                   return
                               } else {
                                   thenCalledOrThrow = true;
                                   reject(reason)
                               }
                           })
                       } else {
                           resolve(x)
                       }
    
                   }catch(e) {
                       if (thenCalledOrThrow) {
                           return
                       } else {
                           thenCalledOrThrow = true;
                           reject(e)
                       }
                   }
               } else {
                   resolve(x)
               }
           }
       }
    
       Promise.prototype.then = function (onResolved, onRjected) {
           let self = this;
           let promise2;
           onResolved = typeof onResolved === 'function' ? onResolved : function(v) {return v};
           onRjected = typeof onRjected === 'function' ? onRjected : function(v) {throw v};
    
           if (self.state === stateArr[0]) {//同一个promise重复调用then就会出现这种情况,而不同的情况会造成要处理的self.data值不一样,所以会多出个resolvePromise函数来统一处理
               return promise2 = new myPromise((resolve, reject) => {
                   setTimeout(() => {////这里用异步的原因就是让then将所有的事做完后(回调函数已经放到回调函数集合的数组里了),再进行resolve。
                       let x = onResolved(self.data);
                       resolvePromise(promise2, x, resolve, reject)
                   })
               })
    
           } else {
               if (self.state === stateArr[1]) {//同一个promise重复调用then就会出现这种情况
                   return promise2 = new myPromise((resolve, reject) => {
                       setTimeout(() => {//这里用异步的原因就是让then将所有的事做完后(回调函数已经放到回调函数集合的数组里了),再进行resolve。
                           let x = onRjected(self.data);
                           resolvePromise(promise2, x, resolve, reject)
                       })
                   })
               } else {
                   return promise2 = new myPromise((resolve, reject) => {
                       self.callbacks.push({//这里不用异步的原因就是因为这是放到回到函数集里执行,那里已经是异步了
                           onResolved: function (value) {
                               try {
                                   let x = onResolved(value);
                                   resolvePromise(promise2, x, resolve, reject)
                               } catch (e) {
                                   reject(e)
                               }
                           },
                           onRjected: function (reason) {
                               try {
                                   let x = onRjected(reason);
                                   resolvePromise(promise2, x, resolve, reject)
                               } catch (e) {
                                   reject(e)
                               }
                           }
                       })
                   })
               }
           }
       }
       }
    

    上诉4个特性的完整代码:

    var myPromise = (function () {
        stateArr = ['fullfilled', 'rejected', 'pending'];//全局中定义下状态集合,方便取用
        //构造函数
        function Promise(resolver) {//构造函数
            let self = this;
            self.state = 'pending';// 初始化状态值
            self.callbacks = [];//存放resolve函数集合和reject函数集合,比如同一个promise多次调用then就会出现累加的情况
            if (typeof resolver !== 'function') {// 构造函数传入的resolver必须是函数
                throw new TypeError(`Promise resolver ${resolver} is not a function`);
            } else {
                if (!!!(this instanceof Promise)) {//不是promise类型的转化为promise类型
                    console.log('创建Promise成功')
                    return new Promise(resolver)
                }
            }
    
    
            function resolve(value) {
                setTimeout(() => {//这里用异步的原因就是让then将所有的事做完后(回调函数已经放到回调函数集合的数组里了),再进行resolve。
                    if (self.state !== stateArr[2]) {//一旦状态改变,就不会再变
                        return
                    } else {
                        //改变状态
                        self.state = stateArr[0];
                        //存储resolve的值
                        self.data = value;
                        self.callbacks.forEach((item, index, arr) => {
                            try {
                                item.onResolved(value);
                            }catch(e) {
                                reject(e)
                            }
                        })
                    }
                })
            }
            function reject(reason) {
                setTimeout(() => {//这里用异步的原因就是让then将所有的事做完后(回调函数已经放到回调函数集合的数组里了),再进行resolve。
                    if (self.state !== stateArr[2]) {//一旦状态改变,就不会再变
                        return
                    } else {
                        //改变状态
                        self.state = stateArr[1];
                        self.data = reason;
                        self.callbacks.forEach((item, index, arr) => {
                            try {
                                item.onRjected(reason);
                            } catch (e) {
                                reject(e)
                            }
                        })
                    }
                })
            }
    
            try {
                resolver(resolve, reject);
            } catch (e) {
                reject(e)
            }
        }
        //promise 结果处理
        function resolvePromise(promise, x, resolve, reject) {//处理resolve的函数
            let thenCalledOrThrow = false;
            if (promise === x){ //不能返回同一个promise
                throw reject(new TypeError(`Chaining cycle detected for promise!`))
            } else {
                if ((x !== null) && typeof x === 'object' || typeof x === 'function') {//处理thenable
                    try {
                        let then = x.then;
                        if (typeof then === 'function') {
                            then.call(x, function rs(rlt) {
                                if (thenCalledOrThrow) {
                                    return
                                } else {
                                    thenCalledOrThrow = true;
                                    resolvePromise(promise, rlt, resolve, reject)
                                }
                            }, function rj(reason) {
                                if (thenCalledOrThrow) {
                                    return
                                } else {
                                    thenCalledOrThrow = true;
                                    reject(reason)
                                }
                            })
                        } else {
                            return resolve(x)
                        }
    
                    }catch(e) {
                        if (thenCalledOrThrow) {
                            return
                        } else {
                            thenCalledOrThrow = true;
                            reject(e)
                        }
                    }
                } else {
                     resolve(x)
                }
            }
        }
        //promise then方法
        Promise.prototype.then = function (onResolved, onRjected) {
            let self = this;
            let promise2;
            onResolved = typeof onResolved === 'function' ? onResolved : function(v) {return v};
            onRjected = typeof onRjected === 'function' ? onRjected : function(v) {throw v};
    
            if (self.state === stateArr[0]) {//同一个promise重复调用then就会出现这种情况,而不同的情况会造成要处理的self.data值不一样,所以会多出个resolvePromise函数来统一处理
                return promise2 = new myPromise((resolve, reject) => {
                    setTimeout(() => {////这里用异步的原因就是让then将所有的事做完后(回调函数已经放到回调函数集合的数组里了),再进行resolve。
                        let x = onResolved(self.data);
                        resolvePromise(promise2, x, resolve, reject)
                    })
                })
    
            } else {
                if (self.state === stateArr[1]) {//同一个promise重复调用then就会出现这种情况
                    return promise2 = new myPromise((resolve, reject) => {
                        setTimeout(() => {//这里用异步的原因就是让then将所有的事做完后(回调函数已经放到回调函数集合的数组里了),再进行resolve。
                            let x = onRjected(self.data);
                            resolvePromise(promise2, x, resolve, reject)
                        })
                    })
                } else {
                    return promise2 = new myPromise((resolve, reject) => {
                        self.callbacks.push({//这里不用异步的原因就是因为这是放到回到函数集里执行,那里已经是异步了
                            onResolved: function (value) {
                                try {
                                    let x = onResolved(value);
                                    resolvePromise(promise2, x, resolve, reject)
                                } catch (e) {
                                    reject(e)
                                }
                            },
                            onRjected: function (reason) {
                                try {
                                    let x = onRjected(reason);
                                    resolvePromise(promise2, x, resolve, reject)
                                } catch (e) {
                                    reject(e)
                                }
                            }
                        })
                    })
                }
            }
        }
    
        return Promise;
    })();
    

    其他API完善:

    var myPromise = (function () {
        stateArr = ['fullfilled', 'rejected', 'pending'];//全局中定义下状态集合,方便取用
        //构造函数
        function Promise(resolver) {//构造函数
            let self = this;
            self.state = 'pending';// 初始化状态值
            self.callbacks = [];//存放resolve函数集合和reject函数集合,比如同一个promise多次调用then就会出现累加的情况
            if (typeof resolver !== 'function') {// 构造函数传入的resolver必须是函数
                throw new TypeError(`Promise resolver ${resolver} is not a function`);
            } else {
                if (!!!(this instanceof Promise)) {//不是promise类型的转化为promise类型
                    console.log('创建Promise成功')
                    return new Promise(resolver)
                }
            }
    
    
            function resolve(value) {
                asyncFn(() => {//这里用异步的原因就是让then将所有的事做完后(回调函数已经放到回调函数集合的数组里了),再进行resolve。
                    if (self.state !== stateArr[2]) {//一旦状态改变,就不会再变
                        return
                    } else {
                        //改变状态
                        self.state = stateArr[0];
                        //存储resolve的值
                        self.data = value;
                        self.callbacks.forEach((item, index, arr) => {
                            try {
                                item.onResolved(value);
                            }catch(e) {
                                reject(e)
                            }
                        })
                    }
                })
            }
            function reject(reason) {
                asyncFn(() => {//这里用异步的原因就是让then将所有的事做完后(回调函数已经放到回调函数集合的数组里了),再进行resolve。
                    if (self.state !== stateArr[2]) {//一旦状态改变,就不会再变
                        return
                    } else {
                        //改变状态
                        self.state = stateArr[1];
                        self.data = reason;
                        self.callbacks.forEach((item, index, arr) => {
                            try {
                                item.onRjected(reason);
                            } catch (e) {
                                reject(e)
                            }
                        })
                    }
                })
            }
    
            try {
                resolver(resolve, reject);
            } catch (e) {
                reject(e)
            }
        }
        //promise 结果处理
        function resolvePromise(promise, x, resolve, reject) {//处理resolve的函数
            let thenCalledOrThrow = false;
            if (promise === x){ //不能返回同一个promise
                throw reject(new TypeError(`Chaining cycle detected for promise!`))
            } else {
                if ((x !== null) && typeof x === 'object' || typeof x === 'function') {//处理thenable
                    try {
                        let then = x.then;
                        if (typeof then === 'function') {
                            then.call(x, function rs(rlt) {
                                // if (thenCalledOrThrow) {
                                    // return
                                // } else {
                                    // thenCalledOrThrow = true;
                                    resolvePromise(promise, rlt, resolve, reject)
                                // }
                            }, function rj(reason) {
                                // if (thenCalledOrThrow) {
                                //     return
                                // } else {
                                //     thenCalledOrThrow = true;
                                    reject(reason)
                                // }
                            })
                        } else {
                            return resolve(x)
                        }
    
                    }catch(e) {
                        // if (thenCalledOrThrow) {
                        //     return
                        // } else {
                        //     thenCalledOrThrow = true;
                            reject(e)
                        // }
                    }
                } else {
                    resolve(x)
                }
            }
        }
        //promise then方法
        Promise.prototype.then = function (onResolved, onRjected) {
            let self = this;
            let promise2;
            onResolved = typeof onResolved === 'function' ? onResolved : function(v) {return v};
            onRjected = typeof onRjected === 'function' ? onRjected : function(v) {throw v};
    
            if (self.state === stateArr[0]) {//同一个promise重复调用then就会出现这种情况,而不同的情况会造成要处理的self.data值不一样,所以会多出个resolvePromise函数来统一处理
                return promise2 = new myPromise((resolve, reject) => {
                    asyncFn(() => {////这里用异步的原因就是让then将所有的事做完后(回调函数已经放到回调函数集合的数组里了),再进行resolve。
                        let x = onResolved(self.data);
                        resolvePromise(promise2, x, resolve, reject)
                    })
                })
    
            } else {
                if (self.state === stateArr[1]) {//同一个promise重复调用then就会出现这种情况
                    return promise2 = new myPromise((resolve, reject) => {
                        asyncFn(() => {//这里用异步的原因就是让then将所有的事做完后(回调函数已经放到回调函数集合的数组里了),再进行resolve。
                            let x = onRjected(self.data);
                            resolvePromise(promise2, x, resolve, reject)
                        })
                    })
                } else {
                    return promise2 = new myPromise((resolve, reject) => {
                        self.callbacks.push({//这里不用异步的原因就是因为这是放到回到函数集里执行,那里已经是异步了
                            onResolved: function (value) {
                                try {
                                    let x = onResolved(value);
                                    resolvePromise(promise2, x, resolve, reject)
                                } catch (e) {
                                    reject(e)
                                }
                            },
                            onRjected: function (reason) {
                                try {
                                    let x = onRjected(reason);
                                    resolvePromise(promise2, x, resolve, reject)
                                } catch (e) {
                                    reject(e)
                                }
                            }
                        })
                    })
                }
            }
        }
        //由then实现catch
        Promise.prototype.catch = function(onRjected) {
            return this.then(null, onRjected)
        }
        //finally实现
        Promise.prototype.finally = function(fn) {
            return this.then((v) => {
                // setTimeout(fn);
                fn();
                return v;
            }, () => {
                // setTimeout(fn);
                fn();
                throw v
            })
        }
        //Promise.resolve的实现
        Promise.resolve = function(v) {
            let promise2;
            if(v instanceof Promise === true) {
                return v
            }else {
                return promise2 = new Promise((resolve, reject) => {
                    resolvePromise(promise2, v, resolve, reject)
                })
            }
        }
        //Promise.reject的实现
        Promise.reject = function(x) {
            let promise = new Promise((resolve, reject) => {
                reject(x)
            })
            return promise        
        }
    
    
        //Promise.all的实现
        Promise.all = function (iterator) {
    
            let len = 0;
            let count = 0;
            let rltArr = [];
            let index = 0;
            return new Promise((resolve, reject) => {
                for (let i of iterator) {
                    len ++;
                    index++;
                    (function(index) {
                        Promise.resolve(i).then(v => {
                            count++;
                            rltArr.push({
                                value: v,
                                index: index
                            });
                            if (count === len) {
                                resolve(sortObjArrToArr(rltArr))
                            }
                        }, e => {
                            reject(e)
                        })
                    })(index)
                }
            })
    
        }
        //Promise.race 的实现
        Promise.race = function(iterator) {
            return new Promise((resolve, reject) => {
                for(let i of iterator) {
                    Promise.resolve(i).then(v => {
                        resolve(v)
                    }, e => {
                        reject(e)
                    })
                }
            })
        }
    
        //Promise.allSettled 的实现
    
        Promise.allSettled = function(iterator) {
            let rltArr = [];
            let len = Object.keys(iterator).length;
            let count = 0;
            let createObj = (state, v, index) => {
                let obj = {};
                obj.status = state;
                obj.value = v;
                Object.defineProperty(obj, 'index', {
                    writable: true,
                    enumerable: false,
                    value: index,
                    configurable: false,
                })
                return obj
            }
            return new Promise((resolve, reject) => {
                let arr = Object.keys(iterator);
                arr.forEach((item, index, arr) => {
                    Promise.resolve(iterator[item]).then(v => {
                        count++;
                        rltArr.push(createObj(state[0], v, index))
                        rltArr.sort((a, b) => {
                            return a.index - b.index
                        })
                        if(len === count) {
                            resolve(rltArr)
                        }
                    }, e => {
                        count++;
                        rltArr.push(createObj(state[1], e, index))
                        rltArr.sort((a, b) => {
                            return a.index - b.index
                        })
                        if(len === count) {
                            resolve(rltArr)
                        }
                    })                
                })
            })
        }
        return Promise;
    })();
    
    const p1 = new myPromise((resolve, reject) => {
        setTimeout(() => {
            resolve('p1')
        },4000)
    })
    const p2 = new myPromise((resolve, reject) => {
        setTimeout(() => {
            reject('p2')
            // resolve('p2')
        },2000)
    })
    const p3 = new myPromise((resolve, reject) => {
        setTimeout(() => {
            // console.log('p3');
            reject('p3')
        },3000)
    })
    
    myPromise.allSettled([p1,p2,p3]).then((v) => {
        console.log('vx', v)
    })
    
    function sortObjArrToArr(objArr) {
       objArr.sort((a, b) => a.index - b.index);
        return objArr.reduce(function(acc, currentValue, index, arr) {
             acc.push(currentValue.value);
             return acc
            }, [])
        }
    //异步函数
    function asyncFn(fn) {
        //降级顺序: asyncFn(microTask, node) => mutationOberserver(microTask, browser) => MessageChannel(maskTask, browser) =>setImmediate => setTimeout
        if(typeof process !== 'undefined' && typeof (process.nextTick) !== 'undefined') {
            process.nextTick(fn)
        }else if(typeof MutationObserver !== 'undefined'){
            let count = 1;
            const observer = new MutationObserver(fn);
            const textNode = document.createTextNode(String(count));
            observer.observe(textNode, {
                characterData: true
            });
            count =  (count + 1) % 2;
            textNode.data = String(count);
        }else if(typeof MessageChannel !== 'undefined') {
            const channel = new MessageChannel();
            channel.port1.onmessage = fn;
            channel.port2.postMessage(0);
        }else if(typeof setImmediate !== 'undefined') {
            setImmediate(fn)
        }else {
            setTimeout(fn)
        }
    }
    

    很多其他版本promise的API也是从上面所述4个基础特性(构造函数,then,resolve,reject)演变出来的,大家可以自行扩展,有问题欢迎留言探讨!

    参考文献:https://www.jianshu.com/p/b4f0425b22a1

    相关文章

      网友评论

          本文标题:你不知道的JS(中卷)笔记——Promise

          本文链接:https://www.haomeiwen.com/subject/fzmblhtx.html