实现状态的变化

JavaScript
JavaScript
// 记录 Promise 的三种状态
const PENDING = 'pending';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected';

class MyPromise {
  /**
   * 创建一个 Promise
   * @param {Function} executor 任务执行器,立即执行
   */
  constructor(executor) {
    this._state = PENDING; // 状态
    this._value = undefined; // 数据

    try {
      executor(this._resolve.bind(this), this._reject.bind(this));
    } catch (error) {
      // 处理错误
      this._reject(error);
      console.error(error);
    }
  }

  /**
   * 更改任务状态
   * @param {String} newState 新状态
   * @param {any} value 相关数据
   */
  _changeState(newState, value) {
    if (this._state !== PENDING) {
      // 目前状态已经更改
      return;
    }

    this._state = newState;
    this._value = value;
  }

  /**
   * 标记当前任务完成
   * @param {any} data 任务完成的相关数据
   */
  _resolve(data) {
    this._changeState(FULFILLED, data);
  }

  /**
   * 标记当前任务失败
   * @param {any} reason 任务失败的相关数据
   */
  _reject(reason) {
    this._changeState(REJECTED, reason);
  }
}
// ------ 测试 ------
let promise1 = new MyPromise((resolve, reject) => {
  resolve('成功');
  reject('失败');
});
console.log(promise1);

let promise2 = new MyPromise((resolve, reject) => {
  reject('失败');
  resolve('成功');
});
console.log(promise2);

创建 then 函数和微队列任务

// 记录 Promise 的三种状态
const PENDING = 'pending';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected';

/**
 * 运行一个微队列任务
 * 把传递的函数放到微队列中(模拟 vue 实现)
 * @param {Function} callback
 */
function runMicroTask(callback) {
  // 判断 node 环境
  // 为了避免「变量未定义」的错误,这里最好加上前缀 globalThis
  // globalThis 是一个关键字,指代全局对象,浏览器环境为 window,node 环境为 global
  if (globalThis.process && globalThis.process.nextTick) {
    // node
    process.nextTick(callback);
  } else if (globalThis.MutationObserver) {
    // 高版本浏览器
    const p = document.createElement('p');
    const observer = new MutationObserver(callback); // 可以做成单例,提高效率,这里简单实现
    observer.observe(p, {
      childList: true, // 观察该元素内部的变化
    });
    p.innerHTML = '1';
  } else {
    // 低版本浏览器
    setTimeout(callback, 0);
  }
}

class MyPromise {
  /**
   * 创建一个 Promise
   * @param {Function} executor 任务执行器,立即执行
   */
  constructor(executor) {
    this._state = PENDING; // 状态
    this._value = undefined; // 数据
    this._handlers = []; // 处理函数形成的队列

    try {
      executor(this._resolve.bind(this), this._reject.bind(this));
    } catch (error) {
      // 处理错误
      this._reject(error);
      console.error(error);
    }
  }

  /**
   * Promise A+ 规范的 then
   * @param {Function} onFulfilled
   * @param {Function} onRejected
   */
  then(onFulfilled, onRejected) {
    return new MyPromise((resolve, reject) => { });
  }

  /**
   * 更改任务状态
   * @param {String} newState 新状态
   * @param {any} value 相关数据
   */
  _changeState(newState, value) {
    if (this._state !== PENDING) {
      // 目前状态已经更改
      return;
    }

    this._state = newState;
    this._value = value;
  }

  /**
   * 标记当前任务完成
   * @param {any} data 任务完成的相关数据
   */
  _resolve(data) {
    this._changeState(FULFILLED, data);
  }

  /**
   * 标记当前任务失败
   * @param {any} reason 任务失败的相关数据
   */
  _reject(reason) {
    this._changeState(REJECTED, reason);
  }
}

执行队列

JavaScript
JavaScript
// 记录 Promise 的三种状态
const PENDING = 'pending';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected';

/**
 * 运行一个微队列任务
 * 把传递的函数放到微队列中(模拟 vue 实现)
 * @param {Function} callback
 */
function runMicroTask(callback) {
  // 判断 node 环境
  // 为了避免「变量未定义」的错误,这里最好加上前缀 globalThis
  // globalThis 是一个关键字,指代全局对象,浏览器环境为 window,node 环境为 global
  if (globalThis.process && globalThis.process.nextTick) {
    // node
    process.nextTick(callback);
  } else if (globalThis.MutationObserver) {
    // 高版本浏览器
    const p = document.createElement('p');
    const observer = new MutationObserver(callback); // 可以做成单例,提高效率,这里简单实现
    observer.observe(p, {
      childList: true, // 观察该元素内部的变化
    });
    p.innerHTML = '1';
  } else {
    // 低版本浏览器
    setTimeout(callback, 0);
  }
}

class MyPromise {
  /**
   * 创建一个 Promise
   * @param {Function} executor 任务执行器,立即执行
   */
  constructor(executor) {
    this._state = PENDING; // 状态
    this._value = undefined; // 数据
    this._handlers = []; // 处理函数形成的队列

    try {
      executor(this._resolve.bind(this), this._reject.bind(this));
    } catch (error) {
      // 处理错误
      this._reject(error);
      console.error(error);
    }
  }

  /**
   * 向处理队列中添加一个函数
   * @param {Function} executor 添加的函数
   * @param {String} state 该函数什么状态下执行
   * @param {Function} resolve 让 then 函数返回的 Promise 成功
   * @param {Function} reject 让 then 函数返回的 Promise 失败
   */
  _pushHandler(executor, state, resolve, reject) {
    this._handlers.push({ executor, state, resolve, reject });
  }

  /**
   * Promise A+ 规范的 then
   * @param {Function} onFulfilled
   * @param {Function} onRejected
   */
  then(onFulfilled, onRejected) {
    return new MyPromise((resolve, reject) => {
      this._pushHandler(onFulfilled, FULFILLED, resolve, reject);
      this._pushHandler(onRejected, REJECTED, resolve, reject);
    });
  }

  /**
   * 更改任务状态
   * @param {String} newState 新状态
   * @param {any} value 相关数据
   */
  _changeState(newState, value) {
    if (this._state !== PENDING) {
      // 目前状态已经更改
      return;
    }

    this._state = newState;
    this._value = value;
  }

  /**
   * 标记当前任务完成
   * @param {any} data 任务完成的相关数据
   */
  _resolve(data) {
    this._changeState(FULFILLED, data);
  }

  /**
   * 标记当前任务失败
   * @param {any} reason 任务失败的相关数据
   */
  _reject(reason) {
    this._changeState(REJECTED, reason);
  }
}
// ------ 测试 ------
let pro = new MyPromise((resolve, reject) => {
  setTimeout(() => {
    resolve('成功');
    console.log(pro);
  }, 1000);
});

pro.then(function A1() { }, function A2() { });
pro.then(function B1() { }, function B2() { });
/**
 MyPromise {
   _state: 'fulfilled',
   _value: '成功',
   _handlers: [
     {
       executor: [Function: A1],
       state: 'fulfilled',
       resolve: [Function: bound _resolve],
       reject: [Function: bound _reject]
     },
     {
       executor: [Function: A2],
       state: 'rejected',
       resolve: [Function: bound _resolve],
       reject: [Function: bound _reject]
     },
     {
       executor: [Function: B1],
       state: 'fulfilled',
       resolve: [Function: bound _resolve],
       reject: [Function: bound _reject]
     },
     {
       executor: [Function: B2],
       state: 'rejected',
       resolve: [Function: bound _resolve],
       reject: [Function: bound _reject]
     }
   ]
 }
 */

遍历执行队列

JavaScript
JavaScript
// 记录 Promise 的三种状态
const PENDING = 'pending';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected';

/**
 * 运行一个微队列任务
 * 把传递的函数放到微队列中(模拟 vue 实现)
 * @param {Function} callback
 */
function runMicroTask(callback) {
  // 判断 node 环境
  // 为了避免「变量未定义」的错误,这里最好加上前缀 globalThis
  // globalThis 是一个关键字,指代全局对象,浏览器环境为 window,node 环境为 global
  if (globalThis.process && globalThis.process.nextTick) {
    // node
    process.nextTick(callback);
  } else if (globalThis.MutationObserver) {
    // 高版本浏览器
    const p = document.createElement('p');
    const observer = new MutationObserver(callback); // 可以做成单例,提高效率,这里简单实现
    observer.observe(p, {
      childList: true, // 观察该元素内部的变化
    });
    p.innerHTML = '1';
  } else {
    // 低版本浏览器
    setTimeout(callback, 0);
  }
}

class MyPromise {
  /**
   * 创建一个 Promise
   * @param {Function} executor 任务执行器,立即执行
   */
  constructor(executor) {
    this._state = PENDING; // 状态
    this._value = undefined; // 数据
    this._handlers = []; // 处理函数形成的队列

    try {
      executor(this._resolve.bind(this), this._reject.bind(this));
    } catch (error) {
      // 处理错误
      this._reject(error);
      console.error(error);
    }
  }

  /**
   * 向处理队列中添加一个函数
   * @param {Function} executor 添加的函数
   * @param {String} state 该函数什么状态下执行
   * @param {Function} resolve 让 then 函数返回的 Promise 成功
   * @param {Function} reject 让 then 函数返回的 Promise 失败
   */
  _pushHandler(executor, state, resolve, reject) {
    this._handlers.push({ executor, state, resolve, reject });
  }

  /**
   * 根据实际情况,执行队列
   */
  _runHandlers() {
    if (this._state === PENDING) {
      // 目前任务仍在挂起
      return;
    }
    while (this._handlers[0]) {
      const handler = this._handlers[0];
      this._runOneHandler(handler);
      this._handlers.shift();
    }
  }

  /**
   * 处理一个 handler
   * @param {Object} handler
   */
  _runOneHandler({ executor, state, resolve, reject }) {

  }

  /**
   * Promise A+ 规范的 then
   * @param {Function} onFulfilled
   * @param {Function} onRejected
   */
  then(onFulfilled, onRejected) {
    return new MyPromise((resolve, reject) => {
      this._pushHandler(onFulfilled, FULFILLED, resolve, reject);
      this._pushHandler(onRejected, REJECTED, resolve, reject);
      this._runHandlers(); // 执行队列(用户可能直接在 new Promise 中执行 resolve 或 reject,此时状态变化,需要立即执行队列)
    });
  }

  /**
   * 更改任务状态
   * @param {String} newState 新状态
   * @param {any} value 相关数据
   */
  _changeState(newState, value) {
    if (this._state !== PENDING) {
      // 目前状态已经更改
      return;
    }

    this._state = newState;
    this._value = value;
    this._runHandlers(); // 状态变化,执行队列
  }

  /**
   * 标记当前任务完成
   * @param {any} data 任务完成的相关数据
   */
  _resolve(data) {
    this._changeState(FULFILLED, data);
  }

  /**
   * 标记当前任务失败
   * @param {any} reason 任务失败的相关数据
   */
  _reject(reason) {
    this._changeState(REJECTED, reason);
  }
}
// ------ 测试 ------
let pro = new MyPromise((resolve, reject) => {
  setTimeout(() => {
    resolve('成功');
    console.log(pro);
  }, 1000);
});

pro.then(function A1() { }, function A2() { });
pro.then(function B1() { }, function B2() { });

// MyPromise { _state: 'fulfilled', _value: '成功', _handlers: [] }

完成核心代码

自此以上为 promise A+ 规范的所有代码

JavaScript
JavaScript
// 记录 Promise 的三种状态
const PENDING = 'pending';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected';

/**
 * 运行一个微队列任务
 * 把传递的函数放到微队列中(模拟 vue 实现)
 * @param {Function} callback
 */
function runMicroTask(callback) {
  // 判断 node 环境
  // 为了避免「变量未定义」的错误,这里最好加上前缀 globalThis
  // globalThis 是一个关键字,指代全局对象,浏览器环境为 window,node 环境为 global
  if (globalThis.process && globalThis.process.nextTick) {
    // node
    process.nextTick(callback);
  } else if (globalThis.MutationObserver) {
    // 高版本浏览器
    const p = document.createElement('p');
    const observer = new MutationObserver(callback); // 可以做成单例,提高效率,这里简单实现
    observer.observe(p, {
      childList: true, // 观察该元素内部的变化
    });
    p.innerHTML = '1';
  } else {
    // 低版本浏览器
    setTimeout(callback, 0);
  }
}

/**
 * 判断一个数据是否是 Promise 对象
 * @param {any} obj
 * @returns
 */
function isPromise(obj) {
  // 必须是一个对象 && 必须有 then 函数
  return !!(obj && typeof obj === 'object' && typeof obj.then === 'function');
}

class MyPromise {
  /**
   * 创建一个 Promise
   * @param {Function} executor 任务执行器,立即执行
   */
  constructor(executor) {
    this._state = PENDING; // 状态
    this._value = undefined; // 数据
    this._handlers = []; // 处理函数形成的队列

    try {
      executor(this._resolve.bind(this), this._reject.bind(this));
    } catch (error) {
      // 处理错误
      this._reject(error);
      console.error(error);
    }
  }

  /**
   * 向处理队列中添加一个函数
   * @param {Function} executor 添加的函数
   * @param {String} state 该函数什么状态下执行
   * @param {Function} resolve 让 then 函数返回的 Promise 成功
   * @param {Function} reject 让 then 函数返回的 Promise 失败
   */
  _pushHandler(executor, state, resolve, reject) {
    this._handlers.push({ executor, state, resolve, reject });
  }

  /**
   * 根据实际情况,执行队列
   */
  _runHandlers() {
    if (this._state === PENDING) {
      // 目前任务仍在挂起
      return;
    }
    while (this._handlers[0]) {
      const handler = this._handlers[0];
      this._runOneHandler(handler);
      this._handlers.shift();
    }
  }

  /**
   * 处理一个 handler()
   * @param {Object} handler
   */
  _runOneHandler({ executor, state, resolve, reject }) {
    // 处理与当前状态 _state 相同的微任务
    runMicroTask(() => {
      if (this._state !== state) {
        // 状态不一致,不处理
        return;
      }

      if (typeof executor !== 'function') {
        // 传递后续处理并非一个函数,与之前的状态保持一致
        this._state === FULFILLED ? resolve(this._value) : reject(this._value);
        return;
      }

      try {
        const result = executor(this._value); // 返回结果有可能是 promise
        if (isPromise(result)) {
          result.then(resolve, reject);
        } else {
          resolve(result);
        }
      } catch (error) {
        reject(error);
        console.error(error);
      }
    });
  }

  /**
   * Promise A+ 规范的 then
   * @param {Function} onFulfilled
   * @param {Function} onRejected
   */
  then(onFulfilled, onRejected) {
    return new MyPromise((resolve, reject) => {
      this._pushHandler(onFulfilled, FULFILLED, resolve, reject);
      this._pushHandler(onRejected, REJECTED, resolve, reject);
      this._runHandlers(); // 执行队列(用户可能直接在 new Promise 中执行 resolve 或 reject,此时状态变化,需要立即执行队列)
    });
  }

  /**
   * 更改任务状态
   * @param {String} newState 新状态
   * @param {any} value 相关数据
   */
  _changeState(newState, value) {
    if (this._state !== PENDING) {
      // 目前状态已经更改
      return;
    }

    this._state = newState;
    this._value = value;
    this._runHandlers(); // 状态变化,执行队列
  }

  /**
   * 标记当前任务完成
   * @param {any} data 任务完成的相关数据
   */
  _resolve(data) {
    this._changeState(FULFILLED, data);
  }

  /**
   * 标记当前任务失败
   * @param {any} reason 任务失败的相关数据
   */
  _reject(reason) {
    this._changeState(REJECTED, reason);
  }
}
// ------ 测试 1 ------
let pro1 = new MyPromise((resolve, reject) => {
  setTimeout(() => {
    reject('失败');
  }, 1000);
});

let pro2 = pro1.then(function A1() { }, undefined);
setTimeout(() => {
  console.log(pro1);
  console.log(pro2);
}, 1500);
// 值穿透
// MyPromise { _state: 'rejected', _value: '失败', _handlers: [] }
// MyPromise { _state: 'rejected', _value: '失败', _handlers: [] }


// ------ 测试 2 ------
let pro3 = new MyPromise((resolve, reject) => {
  setTimeout(() => {
    resolve('成功');
  }, 1000);
});

let pro4 = pro3.then(function A1(data) {
  console.log(data);
  return new MyPromise((resolve, reject) => {
    resolve(1);
  });
});
setTimeout(() => {
  console.log(pro4);
}, 1500);
// 成功
// MyPromise { _state: 'fulfilled', _value: 1, _handlers: [] }


// ------ 测试 3(与官方 promise 互操作) ------
function delay(duraton) {
  return new MyPromise((resolve) => {
    setTimeout(resolve, duraton);
  });
}
(async function () {
  console.log('start');
  await delay(2000);
  console.log('end');
})();

// ------ 测试 4(与官方 promise 互操作) ------
const pro5 = new MyPromise((resolve) => {
  resolve(1);
});

pro5.then((data) => {
  console.log(data);
  return new Promise((resolve) => {
    resolve(2);
  })
}).then(data => {
  console.log(data);
});

catch 和 finally

/**
 * 仅处理失败的场景
 * @param {Function} onRejected
 */
catch(onRejected) {
  return this.then(null, onRejected);
}

/**
 * 无论成功还是失败都会执行回调
 * @param {Function} onSettled
 */
finally(onSettled) {
  return this.then(
    (data) => {
      onSettled();
      return data;
    },
    (reason) => {
      onSettled();
      throw reason;
    }
  );
}

Promise.resolve 和 Promise.reject

JavaScript
JavaScript
/**
 * 返回一个已完成的 Promise
 * 特殊情况:
 * 1. 传递的 data 本身就是 ES6 的 Promise 对象
 * 2. 传递的 data 是 PromiseLike(Promise A+),返回新的 Promise,状态和其保持一致即可
 * @param {any} data
 */
static resolve(data) {
  if (data instanceof MyPromise) {
    return data;
  }
  return new MyPromise((resolve, reject) => {
    if (isPromise(data)) {
      data.then(resolve, reject);
    } else {
      resolve(data);
    }
  });
}

/**
 * 得到一个被拒绝的 Promise
 * @param {any}} reason
 */
static reject(reason) {
  return new MyPromise((resolve, reject) => {
    reject(reason);
  });
}
// ------ 测试 ------
const pro = MyPromise.resolve(new MyPromise((resolve) => resolve(2)));
console.log(pro);

const pro2 = MyPromise.resolve(1);
console.log(pro2);

Promise.all

JavaScript
JavaScript
/**
 * 得到一个新的 Promise
 * 该 Promise 的状态取决于 proms 的执行
 * proms 是一个迭代器,包含多个 Promise
 * 全部 Promise 成功,则返回的 Promise 成功,数据为所有 Promise 成功的数据,并且顺序是按照传入的顺序排列
 * 只要有一个 Promise 失败,则返回的 Promise 失败,原因是第一个失败的 Promise 的原因
 * @param {iterator} proms
 */
static all(proms) {
  return new MyPromise((resolve, reject) => {
    try {
      const results = [];
      let count = 0; // Promise 的总数,利用索引向 results 中放入结果,这样 results 里面的结果是有顺序的
      let fulfilledCount = 0; // 已完成的数量

      for (const p of proms) {
        let i = count;
        count++;
        MyPromise.resolve(p).then( // MyPromise.resolve(p) 包裹一下,p有可能不是 promise
          (data) => {
            fulfilledCount++;
            results[i] = data;
            if (fulfilledCount === count) {
              // 当前是最后一个 Promise 完成了
              resolve(results);
            }
          },
          reject
        );
      }

      if (count === 0) {
        resolve(results);
      }
    } catch (error) {
      reject(error);
      console.error(error);
    }
  });
}
// ------ 测试 ------
MyPromise.all([
  MyPromise.resolve(1),
  MyPromise.resolve(2),
  MyPromise.resolve(3),
]).then(
  res => {
    console.log(res);
  }, err => {
    console.log(err);
  }
);

MyPromise.all([
  MyPromise.resolve(2),
  MyPromise.resolve(3),
  MyPromise.reject('失败'),
]).then(
  res => {
    console.log(res);
  }, err => {
    console.log(err);
  }
);

Promise.allSettled

JavaScript
JavaScript
/**
 * 等待所有的 Promise 有结果之后
 * 该方法返回的 Promise 完成
 * 并且按照顺序将所有结果汇总
 * @param {iterator} proms
 */
static allSettled(proms) {
  const ps = [];
  for (const p of proms) {
    ps.push(
      // p.then: p 有可能不是 promise,所以用 MyPromise.resolve(p) 包裹一下
      MyPromise.resolve(p).then(
        (value) => ({ status: FULFILLED, value }),
        (reason) => ({ status: REJECTED, reason })
      )
    );
  }
  return MyPromise.all(ps);
}
// ------ 测试 ------
const pro = new MyPromise((resolve, reject) => {
  setTimeout(() => {
    reject(1);
  }, 1000);
});
const pro1 = MyPromise.allSettled([
  pro,
  MyPromise.resolve(2),
  MyPromise.resolve(3),
  MyPromise.reject(4),
]);
pro1.then(res => {
  console.log(res);
});
// [
//   { status: 'rejected', reason: 1 },
//   { status: 'fulfilled', value: 2 },
//   { status: 'fulfilled', value: 3 },
//   { status: 'rejected', reason: 4 }
// ]

Promise.race

/**
 * 返回的Promise与第一个有结果的一致
 * @param {iterator} proms
 */
static race(proms) {
  return new MyPromise((resolve, reject) => {
    for (const p of proms) {
      MyPromise.resolve(p).then(resolve, reject);
    }
  });
}

完整代码

// 记录 Promise 的三种状态
const PENDING = 'pending';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected';

/**
 * 运行一个微队列任务
 * 把传递的函数放到微队列中(模拟 vue 实现)
 * @param {Function} callback
 */
function runMicroTask(callback) {
  // 判断 node 环境
  // 为了避免「变量未定义」的错误,这里最好加上前缀 globalThis
  // globalThis 是一个关键字,指代全局对象,浏览器环境为 window,node 环境为 global
  if (globalThis.process && globalThis.process.nextTick) {
    // node
    process.nextTick(callback);
  } else if (globalThis.MutationObserver) {
    // 高版本浏览器
    const p = document.createElement('p');
    const observer = new MutationObserver(callback); // 可以做成单例,提高效率,这里简单实现
    observer.observe(p, {
      childList: true, // 观察该元素内部的变化
    });
    p.innerHTML = '1';
  } else {
    // 低版本浏览器
    setTimeout(callback, 0);
  }
}

/**
 * 判断一个数据是否是 Promise 对象
 * @param {any} obj
 * @returns
 */
function isPromise(obj) {
  return !!(obj && typeof obj === 'object' && typeof obj.then === 'function');
}

class MyPromise {
  /**
   * 创建一个 Promise
   * @param {Function} executor 任务执行器,立即执行
   */
  constructor(executor) {
    this._state = PENDING; // 状态
    this._value = undefined; // 数据
    this._handlers = []; // 处理函数形成的队列

    try {
      executor(this._resolve.bind(this), this._reject.bind(this));
    } catch (error) {
      // 处理错误
      this._reject(error);
      console.error(error);
    }
  }

  /**
   * 向处理队列中添加一个函数
   * @param {Function} executor 添加的函数
   * @param {String} state 该函数什么状态下执行
   * @param {Function} resolve 让 then 函数返回的 Promise 成功
   * @param {Function} reject 让 then 函数返回的 Promise 失败
   */
  _pushHandler(executor, state, resolve, reject) {
    this._handlers.push({ executor, state, resolve, reject });
  }

  /**
   * 根据实际情况,执行队列
   */
  _runHandlers() {
    if (this._state === PENDING) {
      // 目前任务仍在挂起
      return;
    }
    while (this._handlers[0]) {
      const handler = this._handlers[0];
      this._runOneHandler(handler);
      this._handlers.shift();
    }
  }

  /**
   * 处理一个 handler()
   * @param {Object} handler
   */
  _runOneHandler({ executor, state, resolve, reject }) {
    // 处理与当前状态 _state 相同的微任务
    runMicroTask(() => {
      if (this._state !== state) {
        // 状态不一致,不处理
        return;
      }

      if (typeof executor !== 'function') {
        // 传递后续处理并非一个函数,与之前的状态保持一致
        this._state === FULFILLED ? resolve(this._value) : reject(this._value);
        return;
      }

      try {
        const result = executor(this._value); // 返回结果有可能是 promise
        if (isPromise(result)) {
          result.then(resolve, reject);
        } else {
          resolve(result);
        }
      } catch (error) {
        reject(error);
        console.error(error);
      }
    });
  }

  /**
   * Promise A+ 规范的 then
   * @param {Function} onFulfilled
   * @param {Function} onRejected
   */
  then(onFulfilled, onRejected) {
    return new MyPromise((resolve, reject) => {
      this._pushHandler(onFulfilled, FULFILLED, resolve, reject);
      this._pushHandler(onRejected, REJECTED, resolve, reject);
      this._runHandlers(); // 执行队列(用户可能直接在 new Promise 中执行 resolve 或 reject,此时状态变化,需要立即执行队列)
    });
  }

  /**
   * 仅处理失败的场景
   * @param {Function} onRejected
   */
  catch(onRejected) {
    return this.then(null, onRejected);
  }

  /**
   * 无论成功还是失败都会执行回调
   * @param {Function} onSettled
   */
  finally(onSettled) {
    return this.then(
      (data) => {
        onSettled();
        return data;
      },
      (reason) => {
        onSettled();
        throw reason;
      }
    );
  }

  /**
   * 更改任务状态
   * @param {String} newState 新状态
   * @param {any} value 相关数据
   */
  _changeState(newState, value) {
    if (this._state !== PENDING) {
      // 目前状态已经更改
      return;
    }

    // 下面这个判断是为了处理value为Promise的情况
    // 这一段代码课程中没有涉及,特此注释说明
    if (isPromise(value)) {
      value.then(this._resolve.bind(this), this._reject.bind(this));
      return;
    }

    this._state = newState;
    this._value = value;
    this._runHandlers(); // 状态变化,执行队列
  }

  /**
   * 标记当前任务完成
   * @param {any} data 任务完成的相关数据
   */
  _resolve(data) {
    this._changeState(FULFILLED, data);
  }

  /**
   * 标记当前任务失败
   * @param {any} reason 任务失败的相关数据
   */
  _reject(reason) {
    this._changeState(REJECTED, reason);
  }

  /**
   * 返回一个已完成的 Promise
   * 特殊情况:
   * 1. 传递的 data 本身就是 ES6 的 Promise 对象
   * 2. 传递的 data 是 PromiseLike(Promise A+),返回新的 Promise,状态和其保持一致即可
   * @param {any} data
   */
  static resolve(data) {
    if (data instanceof MyPromise) {
      return data;
    }
    return new MyPromise((resolve, reject) => {
      if (isPromise(data)) {
        data.then(resolve, reject);
      } else {
        resolve(data);
      }
    });
  }

  /**
   * 得到一个被拒绝的 Promise
   * @param {any}} reason
   */
  static reject(reason) {
    return new MyPromise((resolve, reject) => {
      reject(reason);
    });
  }

  /**
   * 得到一个新的 Promise
   * 该 Promise 的状态取决于 proms 的执行
   * proms 是一个迭代器,包含多个 Promise
   * 全部 Promise 成功,则返回的 Promise 成功,数据为所有 Promise 成功的数据,并且顺序是按照传入的顺序排列
   * 只要有一个 Promise 失败,则返回的 Promise 失败,原因是第一个失败的 Promise 的原因
   * @param {iterator} proms
   */
  static all(proms) {
    return new MyPromise((resolve, reject) => {
      try {
        const results = [];
        let count = 0; // Promise 的总数,利用索引向 results 中放入结果,这样 results 里面的结果是有顺序的
        let fulfilledCount = 0; // 已完成的数量

        for (const p of proms) {
          let i = count;
          count++;
          MyPromise.resolve(p).then( // MyPromise.resolve(p) 包裹一下,p有可能不是 promise
            (data) => {
              fulfilledCount++;
              results[i] = data;
              if (fulfilledCount === count) {
                // 当前是最后一个 Promise 完成了
                resolve(results);
              }
            },
            reject
          );
        }

        if (count === 0) {
          resolve(results);
        }
      } catch (error) {
        reject(error);
        console.error(error);
      }
    });
  }

  /**
   * 等待所有的 Promise 有结果之后
   * 该方法返回的 Promise 完成
   * 并且按照顺序将所有结果汇总
   * @param {iterator} proms
   */
  static allSettled(proms) {
    const ps = [];
    for (const p of proms) {
      ps.push(
        // p.then: p 有可能不是 promise,所以用 MyPromise.resolve(p) 包裹一下
        MyPromise.resolve(p).then(
          (value) => ({
            status: FULFILLED,
            value,
          }),
          (reason) => ({
            status: REJECTED,
            reason,
          })
        )
      );
    }
    return MyPromise.all(ps);
  }

  /**
   * 返回的Promise与第一个有结果的一致
   * @param {iterator} proms
   */
  static race(proms) {
    return new MyPromise((resolve, reject) => {
      for (const p of proms) {
        MyPromise.resolve(p).then(resolve, reject);
      }
    });
  }
}
打赏作者
您的打赏是我前进的动力
微信
支付宝
评论

中午好👏🏻,我是 ✍🏻   疯狂 codding 中...

粽子

这有关于前端开发的技术文档和你分享。

相信你可以在这里找到对你有用的知识和教程。

了解更多

目录

  1. 1. 实现状态的变化
  2. 2. 创建 then 函数和微队列任务
  3. 3. 执行队列
  4. 4. 遍历执行队列
  5. 5. 完成核心代码
  6. 6. catch 和 finally
  7. 7. Promise.resolve 和 Promise.reject
  8. 8. Promise.all
  9. 9. Promise.allSettled
  10. 10. Promise.race
  11. 11. 完整代码