手撕promise 和async await

44 阅读2分钟

promise

promise处理异步方法,优化了之前回调低于的问题,使得可以链式调用异步方法

// 手撕promise
class MyPromise {
  constructor(executor) {
    // 初始化状态
    this.state = PENDING;
    this.value = undefined;  // 成功值
    this.reason = undefined; // 失败原因
    this.onFulfilledCallbacks = []; // 存储成功回调
    this.onRejectedCallbacks = [];  // 存储失败回调
    
    // 定义resolve函数
    const resolve = (value) => {
      if (this.state === PENDING) {
        this.state = FULFILLED;
        this.value = value;
        // 执行所有成功回调
        this.onFulfilledCallbacks.forEach(fn => fn());
      }
    };
    
    // 定义reject函数
    const reject = (reason) => {
      if (this.state === PENDING) {
        this.state = REJECTED;
        this.reason = reason;
        // 执行所有失败回调
        this.onRejectedCallbacks.forEach(fn => fn());
      }
    };
    
    try {
      // 立即执行executor函数
      executor(resolve, reject);
    } catch (error) {
      // 如果executor执行出错,直接reject
      reject(error);
    }
  }
  
  then(onFulfilled, onRejected) {
    // 2.2.1: onFulfilled和onRejected都是可选的参数
    onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value;
    onRejected = typeof onRejected === 'function' ? onRejected : reason => { throw reason };
    
    // 2.2.7: then方法必须返回一个新的Promise
    const promise2 = new MyPromise((resolve, reject) => {
      const handleFulfilled = () => {
        // 2.2.4: 必须异步执行onFulfilled
        queueMicrotask(() => {
          try {
            const x = onFulfilled(this.value);
            resolve(x)
          } catch (error) {
            reject(error);
          }
        });
      };
      
      const handleRejected = () => {
        // 2.2.4: 必须异步执行onRejected
        queueMicrotask(() => {
          try {
            const x = onRejected(this.reason);
            resolve(x)
          } catch (error) {
            reject(error);
          }
        });
      };
      
      if (this.state === FULFILLED) {
        handleFulfilled();
      } else if (this.state === REJECTED) {
        handleRejected();
      } else if (this.state === PENDING) {
        // 状态为pending,存储回调
        this.onFulfilledCallbacks.push(handleFulfilled);
        this.onRejectedCallbacks.push(handleRejected);
      }
    });
    
    return promise2;
  }
  
  resolvePromise(promise2, x, resolve, reject) {
    if (promise2 === x) {
      return reject(new TypeError('Chaining cycle detected for promise'));
    }
    
    let called = false;
    
    if (x !== null && (typeof x === 'object' || typeof x === 'function')) {
      try {
        const then = x.then;
        if (typeof then === 'function') {
          then.call(x, y => {
            if (called) return;
            called = true;
            this.resolvePromise(promise2, y, resolve, reject);
          }, r => {
            if (called) return;
            called = true;
            reject(r);
          });
        } else {
          resolve(x);
        }
      } catch (error) {
        if (called) return;
        called = true;
        reject(error);
      }
    } else {
      resolve(x);
    }
  }
}

// Promise状态常量
const PENDING = 'pending';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected';

module.exports = MyPromise; 
// promise.all 如果成功的请求,会等都有结果了再返回;有错误的话会马上reject
// promise.allSettle 都有结果了才会返回
// promise.race 一个有结果了马上返回

async await

async await是promsie语法糖,使得代码可读性增强

// 生成器 和 自动执行器 结合
function myAsync(genFen){
    return function(...args){
        const gen = genFen.apply(this, args)
        return new Promise((resolve, reject) => {
            const step = (key, val) => {
                let result = gen[key](val);
                const { done, value } = result
                if(done){
                    resolve(value)
                }
                return Promise.resolve(value).then(res => {
                    step("next", res)
                }).catch(err => {
                    step("throw", err)
                })
            }
            step("next")
        })
    }
}

// 使用示例
const asyncAdd = myAsync(function* () {
    const a = yield Promise.resolve(1);
    const b = yield 2;  // 非 Promise 也能处理
    const c = yield Promise.resolve(3);
    return a + b + c;
});

asyncAdd().then(console.log); // 6