[ js ] 手写promise

class Ps {
  constructor(exector) {
    // 0执行中 1已完成 2已拒绝
    this.state = 0;
    this.sucValue = null;
    this.errValue = null;
    this.sucCallbacks = [];
    this.errCallbacks = [];

    // 执行
    const resolve = value => {
      if (this.state === 0) {
        this.state = 1;
        this.sucValue = value;
        this.sucCallbacks.forEach(cb => cb(this.sucValue));
      }
    }

    const reject = value => {
      if (this.state === 0) {
        this.state = 2;
        this.errValue = value;
        this.errCallbacks.forEach(cb => cb(this.errValue));
      }
    }

    try {
      exector(resolve, reject);
    } catch (err) {
      reject(err);
    }
  }

  then(onResolved, onRejected) {
    // 处理参数
    onResolved = typeof onResolved === 'function' ? onResolved : value => value;
    onRejected = typeof onRejected === 'function' ? onRejected : error => error;

    // 使用queueMicrotask方法将回调函数放入任务队列,保证异步执行
    // 返回promise对象是为了保证使用 .then 之后还能通过 .then 获取值, 如果单纯为了连续使用 .then, 可直接返回this
    // then() { return this }
    // 返回的新promise必须要调用 resolve/reject 方法, 否则会导致死锁
    // 使用 onResolve/onReject 是为了把结果传递给 用户调用 .then 传递进来的回调函数
    // resolve(onResolved(value)) 是为了下一次调用.then可以拿到返回值, 前提是上一次调用.then的回调,有返回值

    return new Ps((resolve, reject) => {
      if (this.state === 1) {
        // 成功
        queueMicrotask(() => {
          resolve(this.sucValue);
        })
      } else if (this.state === 2) {
        // 失败
        queueMicrotask(() => {
          reject(this.errValue);
        })
      } else {
        // 初始化
        this.sucCallbacks.push((v) => {
          queueMicrotask(() => {
            resolve(onResolved(v))
          });
        });
        this.errCallbacks.push((v) => {
          queueMicrotask(() => {
            reject(onRejected(v))
          })
        });
      }
    })
  }

  // then方法的语法糖
  catch(onRejected) {
    this.then(null, onRejected);
  }
}

const ps = new Ps((resolve, reject) => {
  setTimeout(() => {
    const num = Math.random() > 0.5
    return num > 0.5 ? resolve('success333') : reject('error444');
  }, 1000);
})


ps.then(res => {
  console.log('.then print success', res);
  // 如果这里不返回值, 那么下一个.then就拿不到结果
  return 'success1 return to ' + res;
}).then(res2 => {
  console.log('.then print success2', res2);
  // 如果这里不返回值, 那么下一个.then就拿不到结果
  return 'success2 return to ' + res2;
}).then(res3 => {
  console.log('.then print success3', res3);
}).catch(err => {
  console.log('.catch print err', err);
})

image

 

image

 

 
promise设计精妙的地方在于,所有的参数都是函数,所以最简单的理解就是,你给了一个异步函数让promise执行, 然后又给了一会回调让promise执行完成后调用, resolve和reject是promise给你定义的标识符,让用户自己调用,你自己告诉promise你的代码执行完成了,promise再执行你给的回调函数, 形成闭环

真正强大的地方还是 async 和 await 的等待机制
posted @ 2025-08-15 11:02  深海里的星星i  阅读(4)  评论(0)    收藏  举报