zoukankan      html  css  js  c++  java
  • js 实现 promise

    本文仅用于个人技术记录,如误导他人,概不负责。

    本文有参考其他文章,不过地址忘了~~~。

    ===========================================================

    上代码

    const PROMISE_STATUS = {
      PENDING: 'PENDING',
      FULFILLED: 'FULFILLED',
      REJECTED: 'REJECTED'
    }
    
    class ModelPromise {
        static promiseId = 1;
      constructor(initFn) {
        if (typeof initFn !== 'function') {
          throw new Error('must be function')
        }
            this.promiseId = ModelPromise.promiseId;
        this.promiseStatus = PROMISE_STATUS.PENDING;
        this.promiseValue = undefined;
        this.onFulfilledStack = [];
        this.onRejectStack = [];
            this.finallyCallback = undefined;
    
        initFn(this._resolve.bind(this), this._reject.bind(this));
            
            ModelPromise.promiseId++;
      }
    
      _resolve(resolveValue) {
        if (this.promiseStatus !== PROMISE_STATUS.PENDING) { return; }
    
        const runFulfilled = (value) => {
          let onFulfilled;
          while (onFulfilled = this.onFulfilledStack.shift()) {
            onFulfilled(value);
          }
                if (this.finallyCallback) {this.finallyCallback()}
        }
    
        const runRejected = (error) => {
          let onReject;
          while (onReject = this.onRejectStack.shift()) {
            onReject(error);
          }
                if (this.finallyCallback) {this.finallyCallback()}
        }
            
            const run = () => {
                if (resolveValue instanceof ModelPromise) {
                    // 有父子依赖关系时候父值将由子值决定
                    resolveValue.then((value) => {
                        this.promiseStatus = PROMISE_STATUS.FULFILLED;
                        this.promiseValue = value;
                        runFulfilled(value);
                    }, (err) => {
                        this.promiseStatus = PROMISE_STATUS.REJECTED;
                        this.promiseValue = err;
                        runRejected(err);
                    });
                } else {
                    this.promiseStatus = PROMISE_STATUS.FULFILLED;
                    this.promiseValue = resolveValue;
                    runFulfilled(resolveValue);
                }
            }
    
        setTimeout(run);
      }
    
      _reject(err) {
            if (this.promiseStatus !== PROMISE_STATUS.PENDING) { return; }
            
            const run = () => {
                this.promiseStatus = PROMISE_STATUS.REJECTED;
                this.promiseValue = err;
                
                let onReject;
          while (onReject = this.onRejectStack.shift()) {
            onReject(error);
          }
            }
        setTimeout(run);
      }
    
      then(onFulfill, onReject) {
        let _resolveNext;
        let _rejectNext;
            /* 生成一个新的promise等待返回 */
        let newPromise = new ModelPromise((resolve, reject) => {
          _resolveNext = resolve;
          _rejectNext = reject;
        });
            
            const runFulfilled = value => {
                try {
                    if (typeof onFulfill !== 'function') {
                        _resolveNext(value);
                    } else {
                        let onFulfillReturn = onFulfill(value);
                        
                        if (onFulfillReturn instanceof ModelPromise) {
                            onFulfillReturn.then(_resolveNext, _rejectNext);
                        } else {
                            _resolveNext(onFulfillReturn);
                        }
                    }
                } catch(err) {
                    _rejectNext(err);
                }
            }
            
            const runRejected = error => {
                try {
                    if (typeof onReject !== 'function') {
                        _resolveNext(value);
                    } else {
                        let onRejectedReturn = onReject(error);
                        
                        if (onRejectedReturn instanceof ModelPromise) {
                            onRejectedReturn.then(_resolveNext, _rejectNext);
                        } else {
                            _rejectNext(onRejectedReturn);
                        }
                    }
                } catch(err) {
                    _rejectNext(err);
                }
            }
            
            
        if (this.promiseStatus === PROMISE_STATUS.FULFILLED) {
          runFulfilled(this.promiseValue);
        } else if (this.promiseStatus === PROMISE_STATUS.REJECTED) {
          runRejected(this.promiseValue);
        } else {
                /* important!!!! */
                /* 此时推入栈中待执行的不是onFulfill, 而是runFulfilled */
                /* 核心需要关注的是,当一个函数在resolve之后,应当执行then函数的回调函数并且返回值赋值给下一个promise,_resolveNext(onRejectedReturn); */
          this.onFulfilledStack.push(runFulfilled);
          this.onRejectStack.push(runRejected);
        }
        return newPromise;
      }
    
      catch (catchFn) {
        this.then(undefined, catchFn);
      }
        
        finally(finallyCallback) {
            this.finallyCallback = finallyCallback;
        }
        
        static resolve(value) {
            // 如果需要处理的本身就是一个promise,则直接返回使用这个promise
            if (value instanceof ModelPromise) return value;
        let newPromise = new ModelPromise(resolve => {
          resolve(value);
        });
        return newPromise;
      }
        
        static reject(value) {
        let newPromise = new ModelPromise(resolve, reject => {
          reject(value);
        });
        return newPromise;
      }
        
        static race(promiseArr) {
            let newPromise = new ModelPromise((resolve, reject) => {
                promiseArr.forEach((item, index) => {
                    if (item instanceof ModelPromise) {
                        item.then(res => {
                            resolve(res);
                            checkAllResolve();
                        }, err => {
                            reject(err);
                        });
                    } else {
                        resolve(item);
                    }
                });
        });
        return newPromise;
        }
        
        static all(promiseArr) {
        let newPromise = new ModelPromise((resolve, reject) => {
                let promiseValArr = []; //保存所有promise的value,按顺序;
                
                const checkAllResolve = () => {
                    if (promiseValArr.length === promiseArr.length) {
                        resolve(promiseValArr);
                    }
                }
                
                promiseArr.forEach((item, index) => {
                    promiseValArr[index] = undefined;
                    if (item instanceof ModelPromise) {
                        item.then(res => {
                            promiseValArr[index] = res;
                            checkAllResolve();
                        }, err => {
                            reject(err);
                        });
                    } else {
                        promiseValArr[index] = item;
                        checkAllResolve();
                    }
                    
                });
                
          
        });
        return newPromise;
      }
    }
    
    
    /* test start */
    
    let p1 = new ModelPromise((resolve, reject) => {
      console.log("同步执行");
      setTimeout(() => {
        resolve('第一次resolve的值');
        console.log(p1);
        console.log(p2);
        console.log(p3);
        console.log(p4);
        console.log(p5);
      }, 1000);
    });
    
    let p2 = p1.then((res) => {
      console.log('after then1', res);
      return new ModelPromise((resolve, reject) => {
            resolve('新promise的返回值');
        });
    })
    
    let p3 = p2.then((res) => {
      console.log('after then2', res);
      return new ModelPromise((resolve, reject) => {
            setTimeout(() => {
                resolve('3S 后再执行的结果');
            }, 3000);
        });
    });
    // console.log(promise1);
    
    let p4 = p1.then((res) => {
      console.log('接收到第一次resolve的值', res);
      return '第二次then的返回值';
    });
    // console.log(promise2);
    
    let p5 = p3.then((res) => {
        console.log('接收到第二次resolve的值', res);
    })
    .catch((err) => {
        console.log('捕获错误', err);
    });
    
    /* let promiseAll = ModelPromise.all([p1, p2, p3]).then(res => {
        console.log('promiseAll', res);
    }); */
    
    let promiseAll = ModelPromise.race([p1, p2, p3]).then(res => {
        console.log('promise race', res);
    });
    
    promiseAll.finally(() => {
        console.log('promiseAll finally');
    });
  • 相关阅读:
    基于xtrabackup的PointInTime Recovery备份恢复
    使用折半查找法删除
    五月第二周
    MySQL 5.5 外键不能引用分区表主键
    MYSQL 登录漏洞,Percona Server说明
    Detectron2学习笔记 Sanny.Liu
    取客户MAP地址
    DataReader转实体<T>
    从程序员到翻译的感受
    .net中的浅拷贝和深拷贝
  • 原文地址:https://www.cnblogs.com/AlexBlogs/p/10852704.html
Copyright © 2011-2022 走看看