美文网首页
手动实现Promise及all() race()

手动实现Promise及all() race()

作者: 麦芽花生糖 | 来源:发表于2020-02-08 23:13 被阅读0次

手动实现Promise及all() race()

// 三种状态
const PENDING = "pending";
const RESOLVED = "resolved";
const REJECTED = "rejected";

class MyPromise {
  constructor(fn) {
    if (typeof fn !== 'function')
      throw new TypeError('The first parameter of MyPromise must be a function!');
    this.state = PENDING;
    this.value = null;
    this.reason = null;
    this.resolvedCallbacks = [];
    this.rejectedCallbacks = [];

    this.resovle = value => {
      if (this.state === PENDING) {
        this.state = RESOLVED;
        this.value = value;
        setTimeout(() => {
          this.resolvedCallbacks.forEach(cb => cb());
        }, 0);
      }
    }

    this.reject = reason => {
      if (this.state === PENDING) {
        this.state = REJECTED;
        this.reason = reason;
        setTimeout(() => {
          this.rejectedCallbacks.forEach(cb => cb());
        }, 0);
      }
    }

    try {
      fn(this.resovle, this.reject);
    } catch (err) {
      this.reject(err);
    }
  }

  then(onResolved, onRejected) {
    onResolved = typeof onResolved === 'function' ? onResolved : v => v;
    onRejected = typeof onRejected === 'function' ? onRejected : err => { throw err };

    let newPromise = null;
    if (this.state === RESOLVED) {
      return (newPromise = new Promise((resolve, reject) => {
        setTimeout(() => {
          try {
            const x = onResolved(this.value);
            this.resolutionProcedure(newPromise, x, resolve, reject);
          } catch (err) {
            reject(err);
          }
        }, 0);
      }))
    }
    else if (this.state === REJECTED) {
      return (newPromise = new Promise((resolve, reject) => {
        setTimeout(() => {
          try {
            const x = onRejected(this.reason);
            this.resolutionProcedure(newPromise, x, resolve, reject);
          } catch (err) {
            reject(err);
          }
        }, 0);
      }))
    }
    else if (this.state === PENDING) {
      return (newPromise = new Promise((resolve, reject) => {
        this.resolvedCallbacks.push(() => {
          try {
            const x = onResolved(this.value);
            this.resolutionProcedure(newPromise, x, resolve, reject);
          } catch (err) {
            reject(err);
          }
        })
        this.rejectedCallbacks.push(() => {
          try {
            const x = onRejected(this.reason);
            this.resolutionProcedure(newPromise, x, resolve, reject);
          } catch (err) {
            reject(err);
          }
        })
      }))
    }

  }

  catch(onRejected) {
    const onResolved = v => v;
    onRejected = typeof onRejected === 'function' ? onRejected : err => { throw err };

    let newPromise = null;
    if (this.state === RESOLVED) {
      return (newPromise = new Promise((resolve, reject) => {
        setTimeout(() => {
          try {
            resolve(this.value);
          } catch (err) {
            reject(err);
          }
        }, 0);
      }))
    }
    else if (this.state === REJECTED) {
      return (newPromise = new Promise((resolve, reject) => {
        setTimeout(() => {
          try {
            const x = onRejected(this.reason);
            this.resolutionProcedure(newPromise, x, resolve, reject);
          } catch (err) {
            reject(err);
          }
        }, 0);
      }))
    }
    else if (this.state === PENDING) {
      return (newPromise = new Promise((resolve, reject) => {
        this.resolvedCallbacks.push(() => {
          try {
            resolve(this.value);
          } catch (err) {
            reject(err);
          }
        })
        this.rejectedCallbacks.push(() => {
          try {
            const x = onRejected(this.reason);
            this.resolutionProcedure(newPromise, x, resolve, reject);
          } catch (err) {
            reject(err);
          }
        })
      }))
    }
  }

  resolutionProcedure(newPromise, x, resolve, reject) {
    if (newPromise === x)
      return reject(new TypeError('循环引用'));

    if (x instanceof MyPromise) {
      if (x.state === PENDING) {
        x.then(value => {
          x.resolutionProcedure(newPromise, value, resolve, reject);
        }, reject);
      } else {
        x.then(resolve, reject);
      }

      return;
    }

    resolve(x);
  }
}

MyPromise.all = function (promsArr) {
  if (!(promsArr instanceof Array))
    throw new TypeError('The first parameter of MyPromise.all() muset be an Array');

  let n = promsArr.length;
  let values = [];

  return new MyPromise((resolve, reject) => {
    let successCount = 0;
    promsArr.forEach((prom, index) => {
      if (!(prom instanceof MyPromise))
        return;
      if (prom.state === RESOLVED) {
        values[index] = prom.value;
        if (++successCount === n) {
          resolve(values);
        }
      } else if (prom.state === REJECTED) {
        reject(prom.reason);
      } else {
        prom.then(v => {
          values[index] = v;
          if (++successCount === n) {
            resolve(values);
          }
        }, err => reject(err))
      }
    })
  })
}

MyPromise.race = function (promsArr) {
  if (!(promsArr instanceof Array))
    throw new TypeError('The first parameter of MyPromise.all() muset be an Array');

  let n = promsArr.length;
  let failedCount = 0;

  return new MyPromise((resolve, reject) => {
    promsArr.forEach(prom => {
      if (prom.state === RESOLVED) {
        resolve(prom.value);
      } else if (prom.state === REJECTED) {
        if (++failedCount === n) {
          reject(prom.reason);
        }
      } else {
        prom.then(v => {
          resolve(v);
        }, reason => {
          if (++failedCount === n) {
            reject(prom.reason);
          }
        })
      }
    })
  })
}

相关文章

网友评论

      本文标题:手动实现Promise及all() race()

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