jsliang 求职系列

您所在的位置:网站首页 js手写promise jsliang 求职系列

jsliang 求职系列

2022-03-25 14:27| 来源: 网络整理| 查看: 265

/** * @name JsliangPromise * @description 手写 Promise */

/* ——————————————————————————————————————————————— 设置共用函数 ——————————————————————————————————————————————— */// 判断是否为函数const isFunction = (obj) => {  return typeof obj === 'function';};

// 判断是否为对象const isObject = (obj) => {  return !!(obj && typeof obj === 'object');};

// 判断是否为 thenableconst isThenable = (obj) => {  return (    isFunction(obj)    || isObject(obj)  ) && 'then' in obj;};

// 判断是否为 Promiseconst isPromise = (promise) => {  return promise instanceof JsliangPromise;};

/* ——————————————————————————————————————————————— 设置 Promise 状态 ——————————————————————————————————————————————— *//**  1. Promise 有 3 个状态:pending、fulfilled、rejected    * pending:Promise 可以切换到 fulfilled 或者 rejected 状态    * fulfilled:不能迁移到其他状态,必须有个不可变的 value    * rejected:不能迁移到其他状态,必须有个不可变的 reason*/const PENDING = 'pending';const FULFILLED = 'fulfilled';const REJECTED = 'rejected';

/* ——————————————————————————————————————————————— Promise 补充处理 ——————————————————————————————————————————————— */

// 3.6 handleCallback 函数,根据 state 状态,判断是走 fulfilled 路径还是 rejected 路径const handleCallback = (callback, state, result) => {  // 3.6.1 解构  const { onFulfilled, onRejected, resolve, reject } = callback;

  // 3.6.2 判断  try {    // 3.6.3 如果是成功的    if (state === FULFILLED) {      // 3.6.4 判断 onFulfilled 是否为函数      if (isFunction(onFulfilled)) {        // 3.6.5 如果是,将它的返回值作为下一个 Promise 的 result        resolve(onFulfilled(result));      } else {        // 3.6.6 如果不是,直接以当前 Promise 的 result 作为下一个 Promise 的 result        resolve(result);      }    } else if (state === REJECTED) {      if (isFunction(onRejected)) {        resolve(onRejected(result));      } else {        reject(result);      }    }  } catch (error) {    // 3.6.7 如果执行过程抛错,那这个错误,作为下一个 Promise 的 rejected reason 来用    reject(error);  }};

// 2.3.4 清空之前的内容const handleCallbacks = (callbacks, state, result) => {  while (callbacks.length) {    handleCallback(callbacks.shift(), state, result);  }};

// 2.3 状态一旦不是 pending,就不允许再次转换const transition = (promise, state, result) => {  // 2.3.1 如果是 pending,那么就就该成对应的 state 和 result  if (promise.state !== PENDING) {    return;  }

  // 2.3.2 如果不是,那么就进行设置  promise.state = state;  promise.result = result;

  // 2.3.3 当状态变更时,异步清空所有 callbacks  setTimeout(() => {    handleCallbacks(promise.callbacks, state, result);  }, 0);}

// 2.6 一些特殊的 value 被 resolve 时,要做特殊处理。// 这个特殊处理,规范也明确描述了const resolvePromise = (promise, result, resolve, reject) => {  // 2.6.1 如果 result 是当前 Promise 本身,就抛出 TypeError 错误  if (result === promise) {    return reject(new TypeError('Can not fulfill promise with itself'));  }

  // 2.6.2 如果 result 是另一个 Promise,那么沿用当前的 state 和 result 状态  if (isPromise(result)) {    return result.then(resolve, reject);  }

  // 2.6.3 如果 result 是一个 thenable 对象。  // 先去 then 函数,再 call then 函数,重新进入 The Promise resolution procedure 过程  if (isThenable(result)) {    try {      if (isFunction(result.then)) {        return new JsliangPromise(then.bind(result)).then(resolve, reject);      }    } catch (error) {      return reject(error);    }  }

  // 2.6.4 若都不是,直接 resolve result  resolve(result);};

/* ——————————————————————————————————————————————— Promise 实现 ——————————————————————————————————————————————— */

// 2. 设置 Promiseconst JsliangPromise = function(f) {  // 2.1 设置初始化状态  this.state = PENDING;  this.result = null;

  // 3.1 .then() 可以被多次调用,所以需要设置数组进行记录  this.callbacks = [];

  // 2.2 构造 onFulfilled 来切换到 fulfilled,构造 onRejected 来切换到 rejected 状态  const onFulfilled = value => transition(this, FULFILLED, value);  const onRejected = reason => transition(this, REJECTED, reason);

  // 2.3 配合 ignore 来保证 resolve/reject 只有一次调用作用  let ignore = false;    // 2.4 设置 resolve 的处理方式  let resolve = (value) => {    if (ignore) {      return;    }    ignore = true;    // 2.5 对 resolve 进行 3 条规则判定    resolvePromise(this, value, onFulfilled, onRejected);  };

  let reject = (reason) => {    if (ignore) {      return;    }    ignore = true;    onRejected(reason);  }

  // 2.6 进行尝试  try {    // 2.6.1 将 resolve 和 reject 作为参数传入 f 函数,方便调用    f(resolve, reject);  } catch (error) {    // 2.6.2 如果 f 函数执行报错,那么错误就作为 reject 的 reason 来用    reject(error);  }}

// 3. Promise.then 方法JsliangPromise.prototype.then = function (onFulfilled, onRejected) {  // 3.2 .then() 方法返回 Promise,所以需要 return 一个出去  return new JsliangPromise((resolve, reject) => {

    // 3.3 设置 callback    const callback = { onFulfilled, onRejected, resolve, reject };

    // 3.4 如果 state 处于 pending 状态,就存储进 callbacks 列表里    if (this.state === PENDING) {      this.callbacks.push(callback);    } else {      // 3.5 如果不是,就扔个 handleCallback 去处理      // 至于为什么用 setTimeout?因为我们模拟不了微任务,那就用宏任务去解决吧      setTimeout(() => {        handleCallback(callback, this.state, this.result);      }, 0);    }  });};

/* ——————————————————————————————————————————————— 测试 ——————————————————————————————————————————————— */

const promise = new JsliangPromise((resolve, reject) => {  setTimeout(() => {    console.log(1);    resolve(2);  }, 1000);});

promise.then((res) => {  console.log('res 1:', res);  return 3;}).then((res) => {  console.log('res 2:', res);});



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3