牛刀小试-Promise

Promise

// 先定义三个常量表示状态
const PENDING = "pending";
const FULFILLED = "fulfilled";
const REJECTED = "rejected";

class MyPromise {
  constructor(executor) {
    //executor 是一个执行器,进入会立即执行
    try {
      executor(this.resolve, this.reject);
    } catch (error) {
      this.reject(error);
    }
  }

  //初始化变量
  status = PENDING;
  value = null; //成功
  reason = null; //失败

  // 存储成功回调函数
  onFulfilledCallbacks = [];
  // 存储失败回调函数
  onRejectedCallbacks = [];

  // resolve和reject为什么要用箭头函数?
  // 如果直接调用的话,普通函数this指向的是window或者undefined
  // 用箭头函数就可以让this指向当前实例对象
  // 更改成功后的状态
  resolve = value => {
    if (this.status === PENDING) {
      this.value = value;
      this.status = FULFILLED;
      // 判断成功回调是否存在,如果存在就调用
      while (this.onFulfilledCallbacks.length) {
        // Array.shift() 取出数组第一个元素,然后()调用,
        // shift不是纯函数,取出后,数组将失去该元素,直到数组为空
        this.onFulfilledCallbacks.shift()(value);
      }
    }
  };
  // 更改失败后的状态
  reject = reason => {
    if (this.status === PENDING) {
      this.reason = reason;
      this.status = REJECTED;
      // 判断失败回调是否存在,如果存在就调用
      while (this.onRejectedCallbacks.length) {
        this.onRejectedCallbacks.shift()(reason);
      }
    }
  };

  then(onFulfilled, onRejected) {
    // 如果不传,就使用默认函数
    onFulfilled = typeof onFulfilled === "function" ? onFulfilled : value => value;
    onRejected =
      typeof onRejected === "function"
        ? onRejected
        : reason => {
            throw reason;
          };

    // 为了链式调用这里直接创建一个 MyPromise,并在后面 return 出去
    const promise2 = new MyPromise((resolve, reject) => {
      const fulfilledMicrotask = () => {
        // 创建一个微任务等待 promise2 完成初始化
        queueMicrotask(() => {
          try {
            // 获取成功回调函数的执行结果
            const x = onFulfilled(this.value);
            // 传入 resolvePromise 集中处理
            resolvePromise(promise2, x, resolve, reject);
          } catch (error) {
            reject(error);
          }
        });
      };
      const rejectedMicrotask = () => {
        // 创建一个微任务等待 promise2 完成初始化
        queueMicrotask(() => {
          try {
            // 调用失败回调,并且把原因返回
            const x = realOnRejected(this.reason);
            // 传入 resolvePromise 集中处理
            resolvePromise(promise2, x, resolve, reject);
          } catch (error) {
            reject(error);
          }
        });
      };

      // 判断状态
      if (this.status === FULFILLED) {
        fulfilledMicrotask();
      } else if (this.status === REJECTED) {
        rejectedMicrotask();
      } else if (this.status === PENDING) {
        // 等待
        // 因为不知道后面状态的变化情况,所以将成功回调和失败回调存储起来
        // 等到执行成功失败函数的时候再传递
        this.onFulfilledCallbacks.push(fulfilledMicrotask);
        this.onRejectedCallbacks.push(rejectedMicrotask);
      }
    });

    return promise2;
  }
  // resolve 静态方法
  static resolve(parameter) {
    //如果传入是 MyPromise 就直接返回
    if (parameter instanceof MyPromise) {
      return parameter;
    }
    //否则返回个 MyPromise 包着它
    return new MyPromise(resolve => {
      resolve(parameter);
    });
  }

  // reject 静态方法
  static reject(reason) {
    return new MyPromise((resolve, reject) => {
      reject(reason);
    });
  }
}
//解析
function resolvePromise(promise, x, resolve, reject) {
  if (promise == x) {
    return reject(new TypeError("Chaining cycle detected for promise #<Promise>"));
  }

  //判断 x 是不是 MyPromise 实例对象
  if (x instanceof MyPromise) {
    //如果是则表示x为 promise ,
    //执行 x ,调用 then 方法,目的是将其状态变为 fulfilled或者rejected
    //x.then(value => resolve(value),reason => reject(reason))
    x.then(resolve, reject);
  } else {
    //普通值
    resolve(x);
  }
}

/* const promise = new MyPromise((resolve, reject) => {
  resolve("success");
});

// 这个时候将promise定义一个p1,然后返回的时候返回p1这个promise
const p1 = promise.then(value => {
  console.log(1);
  console.log("resolve", value);
  return p1;
});

// 运行的时候会走reject
p1.then(
  value => {
    console.log(2);
    console.log("resolve", value);
  },
  reason => {
    console.log(3);
    console.log(reason.message);
  }
); */
// promise
//   .then(value => {
//     console.log(1);
//     console.log("resolve", value);
//     return other();
//   })
//   .then(value => {
//     console.log(2);
//     console.log("resolve", value);
//   });

// 第一个then方法中的错误要在第二个then方法中捕获到
/* promise
  .then(
    value => {
      console.log(1);
      console.log("resolve", value);
      throw new Error("then error");
    },
    reason => {
      console.log(2);
      console.log(reason.message);
    }
  )
  .then(
    value => {
      console.log(3);
      console.log(value);
    },
    reason => {
      console.log(4);
      console.log(reason.message);
    }
  ); */

// promise.then().then().then(value => console.log(value))
MyPromise.resolve()
  .then(() => {
    console.log(0);
    return MyPromise.resolve(4);
  })
  .then(res => {
    console.log(res);
  });

  • Promise.all:有 rejected 会直接返回并且只返回这个rejected,否则等全部返回
  • Promise.allSettled(都解决的):全部执行完再返回,返回值里有 status [ “fulfilled” 或 “rejected” ]
  • Promise.race(竞速的):返回第一个执行完的,不论是否 rejected
  • Promise.any:返回第一个成功的,如果全部失败会进 catch
    以上方法参数中有非 promise情况 则按成功状态处理

Promise.all

/**
 * @description
 * 接收一个Promise数组,数组中如有非Promise项,则此项当做成功
 * 如果所有Promise都成功,则返回成功结果数组
 * 如果有一个Promise失败,则返回这个失败结果
 * @param
 * @author lg
 * @date 2022-02-13 13:40:19
 */
function promiseAll(args) {
  const promises = Array.from(args);
  const len = promises.length;
  let count = 0;
  let resultList = [];

  //  将三个promise存到一个大的promise中,异步等待执行
  return new Promise((resolve, reject) => {
    /**
     * @param result: promise 结果
     * @param index: promise 顺序
     */
    function addToResultList(result, index) {
      count++;
      resultList[index] = result;
      if (count === len) {
        resolve(resultList);
      }
    }

    promises.forEach((promise, index) => {
      //如果数组里面是都是promise实例
      if (promise instanceof Promise) {
        promise.then(result => {
          addToResultList(result, index);
        }, reject);
      } else {
        //数组中有非Promise实例,此项当做成功;
        addToResultList(promise, index);
      }
    });
  });
}

let pro1 = Promise.resolve(1);
let pro2 = 2;
let pro3 = Promise.resolve(3);

promiseAll([pro1, pro2, pro3])
  .then(data => {
    console.log("result", data);
  })
  .catch(err => {
    console.log("err", err);
  });

Promise.allSettled

/**
 * @description
 * 接收一个Promise数组,数组中如有非Promise项,则此项当做成功
 * 把每一个Promise的结果,集合成数组,返回
 * @param
 * @author lg
 * @date 2022-02-13 13:49:59
 */

function promiseAllSettled(args) {
  const promises = Array.from(args);
  const resultList = [];
  const len = promises.length;
  let count = 0;
  return new Promise((resolve, reject) => {
    if (len === 0) {
      resolve(resultList);
    }

    /**
     * @param result: promise 结果
     * @param index: promise 顺序
     */
    function addToResultList(result, index) {
      count++;
      resultList[index] = result;
      if (count === len) {
        resolve(resultList);
      }
    }
    promises.forEach((promise, index) => {
      if (promise instanceof Promise) {
        promise.then(
          res => {
            addToResultList(
              {
                status: "fulfilled",
                value: res
              },
              index
            );
          },
          err => {
            addToResultList(
              {
                status: "rejected",
                reason: err
              },
              index
            );
          }
        );
      } else {
        addToResultList(
          {
            status: "fulfilled",
            value: promise
          },
          index
        );
      }
    });
  });
}

const p1 = Promise.resolve(1);
const p2 = new Promise(resolve => {
  setTimeout(() => resolve(2), 1000);
});
const p3 = new Promise(resolve => {
  setTimeout(() => resolve(3), 3000);
});

const p4 = Promise.reject("err4");
const p5 = Promise.reject("err5");
const p11 = promiseAllSettled([p1, p2, p4]).then(res =>
  console.log(JSON.stringify(res, null, 2))
);

Promise.race

/**
 * @description
 * 接收一个Promise数组,数组中如有非Promise项,则此项当做成功
 * 哪个Promise最快得到结果,就返回那个结果,无论成功失败
 * @param
 * @author lg
 * @date 2022-02-13 13:42:44
 */

function promiseRace(args) {
  const promises = Array.from(args); //如果参数不是数组,转成数组

  return new Promise((resolve, reject) => {
    promises.forEach(promise => {
      if (promise instanceof Promise) {
        //谁先有结果就返回那个结果,无论成功失败
        promise.then(
          res => {
            resolve(res);
          },
          err => {
            reject(err);
          }
        );
      } else {
        resolve(promise);
      }
    });
  });
}
let pro1 = Promise.resolve(1);
let pro2 = 2;
let pro3 = Promise.resolve(3);

promiseRace([pro1, pro2, pro3])
  .then(data => {
    console.log("result", data);
  })
  .catch(err => {
    console.log("err", err);
  });

Promise.any

/**
 * @description
 * 接收一个Promise数组,数组中如有非Promise项,则此项当做成功
 * 如果有一个Promise成功,则返回这个成功结果
 * 如果所有Promise都失败,则报错
 * @param
 * @author lg
 * @date 2022-02-13 17:17:34
 */

function promiseAny(args) {
  const promises = Array.from(args);
  const len = promises.length;
  let count = 0;
  return new Promise((resolve, reject) => {
    if (len === 0) return resolve([]);
    promises.forEach(promise => {
      if (promise instanceof Promise) {
        promise.then(
          res => {
            resolve(res);
          },
          err => {
            count++;
            if (count === len) reject("All promises were rejected");
          }
        );
      } else {
        resolve(promise);
      }
    });
  });
}

let pro1 = Promise.reject(1);
let pro2 = Promise.reject(1);
let pro3 = Promise.reject(3);

promiseAny([pro1, pro2, pro3])
  .then(value => {
    console.log("value: ", value);
  })
  .catch(err => {
    console.log("err: ", err);
  });

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值