美文网首页
实现一个符合规范的Promise

实现一个符合规范的Promise

作者: TerdShow | 来源:发表于2019-07-30 11:40 被阅读0次
    const PENDING = 'pengding';
    const SUCCEED = 'fulfilled';
    const FAILED = 'rejected';
    
    function resolvePromise(promise2, x, resolve, reject) {
      var called;
      if (promise2 === x) {
        return reject(new TypeError('Chaining cycle detected for promise #<Promise>'));
      }
      if (typeof x === 'function' || (typeof x === 'object' && x != null)) {
        try {
          let then = x.then;
          if (typeof then === 'function') {
            if (called) return;
            called = true;
            then.call(x, y => {
              resolvePromise(promise2, y, resolve, reject);
            }, r => {
              reject(r);
            })
          } else {
            if (called) return;
            called = true;
            resolve(x);
          }
        } catch (e) {
          if (called) return;
          called = true;
          reject(e);
        }
      } else {
        resolve(x);
      }
    }
    
    function isPromise(p) {
      if (typeof p === 'function' || (typeof p === 'object' && p != null)) {
        return typeof p.then === 'function'
      }
      return false;
    }
    
    class Promise {
      constructor(excutor) {
        this.state = PENDING;
        this.value = undefined;
        this.reason = undefined;
        this.onResolvedCallbacks = [];
        this.onRejectedCallbacks = [];
        const resolve = value => {
          if (value instanceof Promise) {
            return value.then(resolve, reject);
          }
          if (this.state === PENDING) {
            this.state = SUCCEED;
            this.value = value;
            this.onResolvedCallbacks.forEach(cb => cb());
          }
        }
        const reject = reason => {
          if (this.state === PENDING) {
            this.state = FAILED;
            this.reason = reason;
            this.onRejectedCallbacks.forEach(cb => cb());
          }
        }
        try {
          excutor(resolve, reject);
        } catch (err) {
          reject(err);
        }
      }
      then(onFulfilled, onRejected) {
        onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : val => val;
        onRejected = typeof onRejected === 'function' ? onRejected : err => {
          throw err
        };
        var promise2;
        promise2 = new Promise((resolve, reject) => {
          if (this.state === SUCCEED) {
            setTimeout(() => {
              try {
                let x = onFulfilled(this.value);
                resolvePromise(promise2, x, resolve, reject);
              } catch (e) {
                reject(e)
              }
            })
          }
          if (this.state === FAILED) {
            setTimeout(() => {
              try {
                let x = onRejected(this.reason);
                resolvePromise(promise2, x, resolve, reject);
              } catch (e) {
                reject(e)
              }
            })
          }
          if (this.state === PENDING) {
            this.onResolvedCallbacks.push(() => {
              setTimeout(() => {
                try {
                  let x = onFulfilled(this.value);
                  resolvePromise(promise2, x, resolve, reject);
                } catch (e) {
                  reject(e)
                }
              })
            })
            this.onRejectedCallbacks.push(() => {
              setTimeout(() => {
                try {
                  let x = onRejected(this.reason);
                  resolvePromise(promise2, x, resolve, reject);
                } catch (e) {
                  reject(e)
                }
              })
            })
          }
        })
        return promise2;
      }
      catch (errCallback) {
        return this.then(null, reject(errCallback));
      }
      static resolve(value){
        return new Promise((resolve, reject) => {
          resolve(value);
        })
      }
      static reject(reason){
        return new Promise((resolve, reject) => {
          reject(reason);
        })
      }
      static all(promises) {
        return new Promise((resolve, reject) => {
          let arr = [];
          let i = 0;
          const processData = (key, value) => {
            arr[key] = value;
            if (++i == promises.length) {
              resolve(arr);
            }
          }
          for (let i = 0; i < promises.length; i++) {
            let current = promises[i];
            if (isPromise(current)) {
              current.then(y => {
                processData(i, y)
              }, reject);
            } else {
              processData(i, current);
            }
          }
        })
      }
      static race(promises) {
        for (let i = 0; i < promises.length; i++) {
          let current = promises[i];
          if (isPromise(current)) {
            current.then(resolve, reject);
          } else {
            resolve(current);
          }
        }
      }
      static try(tryCallback) {
        return new Promise((resolve, reject) => {
          return Promise.resolve(tryCallback()).then(resolve, reject);
        })
      }
    }
    Promise.prototype.finally = (callback) => {
      return this.then(data => {
        return new Promise((resolve, reject) => {
          return resolve(callback());
        }).then(() => data);
      }, err => {
        return new Promise((resolve, reject) => {
          return resolve(callback());
        }).then(() => {
          throw err
        });
      })
    }
    module.exports = Promise;
    

    相关文章

      网友评论

          本文标题:实现一个符合规范的Promise

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