js 實現 promise

本文僅用於我的技術記錄,如誤導他人,概不負責。promise

本文有參考其餘文章,不過地址忘了~~~。函數

 

===========================================================this

上代碼spa

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');
});
相關文章
相關標籤/搜索