手写 promise

// 1、基本架构:
//   状态
//   then
//   执行器函数 executor

// 2、executor、resolve、reject
// 3、then 同步下调用
// 4、then 异步下调用
// 5、then 链式调用
//   返回 Promise
//   then 函数递归返回常量结果,供下个 then 使用
//   考虑 then 成功的回调为 null 的情况

class Promise {
  static PENDING = "pending";
  static RESOLVED = "resolved";
  static REJECTED = "rejected";

  static resolve(value) {
    return new Promise((resolve, reject) => {
      resolve(value);
    });
  }

  static reject(reason) {
    return new Promise((resolve, reject) => {
      reject(reason);
    });
  }

  constructor(executor) {
    this.state = Promise.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 === Promise.PENDING) {
        this.state = Promise.RESOLVED;
        this.value = value;

        this.onResolvedCallbacks.forEach((fn) => fn());
      }
    };
    const reject = (reason) => {
      this.state = Promise.REJECTED;
      this.reason = reason;
      this.onRejectedCallbacks.forEach((fn) => fn());
    };

    try {
      executor(resolve, reject);
    } catch (error) {
      reject(error);
    }
  }

  then(onFulfilled, onRejected) {
    onFulfilled =
      typeof onFulfilled === "function" ? onFulfilled : (value) => value;
    onRejected =
      typeof onRejected === "function"
        ? onRejected
        : (reason) => {
            throw reason;
          };

    let promise = new Promise((resolve, reject) => {
      if (this.state === Promise.PENDING) {
        this.onResolvedCallbacks.push(() => {
          setTimeout(() => {
            try {
              let x = onFulfilled(this.value);
              resolvePromise(promise, x, resolve, reject);
            } catch (error) {
              reject(error);
            }
          });
        });
        this.onRejectedCallbacks.push(() => {
          setTimeout(() => {
            try {
              let x = onRejected(this.reason);
              resolvePromise(promise, x, resolve, reject);
            } catch (error) {
              reject(error);
            }
          });
        });
      }

      if (this.state === Promise.RESOLVED) {
        setTimeout(() => {
          try {
            let x = onFulfilled(this.value);
            resolvePromise(promise, x, resolve, reject);
          } catch (error) {
            reject(error);
          }
        });
      }

      if (this.state === Promise.REJECTED) {
        setTimeout(() => {
          try {
            let x = onRejected(this.reason);
            resolvePromise(promise, x, resolve, reject);
          } catch (error) {
            reject(error);
          }
        });
      }
    });

    return promise;
  }

  catch(onRejected) {
    return this.then(null, onRejected);
  }

  all(arr) {
    let count = 0;
    let result = [];

    return new Promise((resolve, reject) => {
      for (let i = 0; i < arr.length; i++) {
        Promise.resolve(arr[i])
          .then((res) => {
            result[i] = res;
            if (++count === arr.length) {
              resolve(res);
            }
          })
          .catch((error) => {
            reject(error);
          });
      }
    });
  }

  race(arr) {
    return new Promise((resolve, reject) => {
      arr.forEach((item) => Promise.resolve(item).then(resolve, reject));
    });
  }

  finally(callback) {
    return this.then(
      (value) => {
        return Promise.resolve(callback()).then(() => value);
      },
      (reason) => {
        return Promise.resolve(callback()).then(() => {
          throw reason;
        });
      }
    );
  }

  allSettled(arr) {
    let count = 0;
    let result = [];

    return new Promise((resolve, reject) => {
      const fn = (i, data) => {
        if (count === arr.length) {
          resolve(result);
        }

        result[i] = data;
        count++;
      };

      for (let i = 0; i < arr.length; i++) {
        Promise.resolve(arr[i])
          .then((res) => {
            fn(i, { status: "fulfilled", value: res });
          })
          .catch((error) => {
            fn(i, { status: "rejected", reason: error });
          });
      }
    });
  }

  // from Node Util.promisify
  promisify(f) {
    return function (...args) {
      return new Promise((resolve, reject) => {
        function callback(error, result) {
          if (error) {
            reject(error);
          } else {
            resolve(result);
          }
        }

        args.push(callback);

        f.call(this, ...args);
      });
    };
  }

  // from Node Util.promisifyAll
  promisifyAll(obj) {
    for (let key in obj) {
      if (typeof obj[key] === "function") {
        obj[key] = this.promisify(obj[key]);
      }
    }
  }
}

function resolvePromise(promise, x, resolve, reject) {
  // let promise = new Promise((resolve) => {
  //   resolve(1);
  // }).then((res) => {
  //   return promise;
  // });

  if (x === promise) {
    throw TypeError("循环引用");
  }

  if ((typeof x === "object" && x !== null) || typeof x === "function") {
    let called;

    try {
      let then = x.then;

      if (typeof then === "function") {
        then.call(
          x,
          (y) => {
            if (called) return;
            called = true;
            resolvePromise(promise, y, resolve, reject);
          },
          (r) => {
            if (called) return;
            called = true;
            reject(r);
          }
        );
      } else {
        // x: { then: {} }
        if (called) return;
        called = true;
        resolve(x);
      }
    } catch (error) {
      if (called) return;
      called = true;
      reject(error);
    }
  } else {
    // 返回了常量,直接 resolve
    resolve(x);
  }
}

const p = new Promise((resolve, reject) => {
  reject(1);
});

p.catch((error) => {
  console.log("error + ", error);
  return error;
}).then((res) => {
  console.log(res);
});

Promise.deferred = function () {
  let dfd = {};
  dfd.promise = new Promise((resolve, reject) => {
    dfd.resolve = resolve;
    dfd.reject = reject;
  });
  return dfd;
};

module.exports = Promise;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
当然可以!以下是一个简单的手写Promise的示例: ```javascript class Promise { constructor(executor) { this.state = 'pending'; this.value = undefined; this.reason = undefined; this.onResolveCallbacks = []; this.onRejectCallbacks = []; const resolve = (value) => { if (this.state === 'pending') { this.state = 'fulfilled'; this.value = value; this.onResolveCallbacks.forEach(callback => callback()); } }; const reject = (reason) => { if (this.state === 'pending') { this.state = 'rejected'; this.reason = reason; this.onRejectCallbacks.forEach(callback => callback()); } }; try { executor(resolve, reject); } catch (error) { reject(error); } } then(onFulfilled, onRejected) { const fulfilledHandler = typeof onFulfilled === 'function' ? onFulfilled : value => value; const rejectedHandler = typeof onRejected === 'function' ? onRejected : reason => { throw reason; }; const promise2 = new Promise((resolve, reject) => { const fulfillHandlerWrapper = () => { setTimeout(() => { try { const result = fulfilledHandler(this.value); resolvePromise(promise2, result, resolve, reject); } catch (error) { reject(error); } }, 0); }; const rejectHandlerWrapper = () => { setTimeout(() => { try { const result = rejectedHandler(this.reason); resolvePromise(promise2, result, resolve, reject); } catch (error) { reject(error); } }, 0); }; if (this.state === 'fulfilled') { fulfillHandlerWrapper(); } else if (this.state === 'rejected') { rejectHandlerWrapper(); } else { this.onResolveCallbacks.push(fulfillHandlerWrapper); this.onRejectCallbacks.push(rejectHandlerWrapper); } }); return promise2; } catch(onRejected) { return this.then(null, onRejected); } } function resolvePromise(promise, result, resolve, reject) { if (promise === result) { return reject(new TypeError('Chaining cycle detected for promise')); } let thenCalledOrThrow = false; if (result instanceof Promise) { result.then( value => resolvePromise(promise, value, resolve, reject), reason => reject(reason) ); } else if (result !== null && (typeof result === 'object' || typeof result === 'function')) { try { const then = result.then; if (typeof then === 'function') { then.call( result, value => { if (thenCalledOrThrow) return; thenCalledOrThrow = true; resolvePromise(promise, value, resolve, reject); }, reason => { if (thenCalledOrThrow) return; thenCalledOrThrow = true; reject(reason); } ); } else { resolve(result); } } catch (error) { if (thenCalledOrThrow) return; thenCalledOrThrow = true; reject(error); } } else { resolve(result); } } ``` 这只是一个基本的实现,还有很多细节和功能可以改进。希望对你有所帮助!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值