5K字 由浅入深聊聊Promise实现原理

概念

Promise 是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更合理和更强大。它由社区最早提出和实现,ES6 将其写进了语言标准,统一了用法,原生提供了Promise对象。

所谓Promise,简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。从语法上说,Promise 是一个对象,从它可以获取异步操作的消息。Promise 提供统一的 API,各种异步操作都可以用同样的方法进行处理。

Promise 拉出来单练

那我们先把Promise拉出来练练,看看是什么玩意,在控制台中打印看下

  • 首先我们看出在new Promise时,需要传入一个回调函数
  • 它是一个类,并且会返回一个Promise对象
  • 那还可以看出它有constructor构造函数,还有catchfinallythen三个方法

那我们根据上述分析出的信息,简单实现一下

class CustomPromise {
  constructor(callBack) {}
  catch() {}
  then() {}
  finally() {}
}
const customPromise = new CustomPromise()
console.log(customPromis) 

看下我们自己简单实现的输出结果

const promise = new Promise((resolve, reject) => {
  console.log("hellow Promise");
});
console.log(promise); 

那我们来看看打印结果,能分析出什么结果

  • hellow promise 在控制台被输出了,那是不是说我们传入的回调函数被立即执行了,那说明传入的是一个执行器

那再改进一下我们的CustomPromise

class CustomPromise {
  constructor(executor) {
      executor()}
  catch() { }
  then() { }
  finally() { }
}
const customPromise = new CustomPromise((resolve, reject) => {
  console.log('hellow Promise')
})
console.log(customPromise) 

Promise基本原理与基本特征

那我们来看看我们所熟知的Promise的基本原理

  • 首先我们在调用Promise时,会返回一个Promise对象。
  • 构建Promise对象时,需要传入一个executor函数,Promise的主要业务流程都在executor函数中执行。
  • 如果运行在excutor函数中的业务执行成功了,会调用resolve函数;如果执行失败了,则调用reject函数。
  • Promise的状态不可逆,同时调用resolve函数和reject函数,默认会采取第一次调用的结果。

结合Promise/A+规范,我们还可以分析出哪些基本特征

Promise/A+的规范比较多,在这列出一下核心的规范

  • promise有三个状态:pending,fulfilled,rejected,默认状态是pending。
  • promise有一个value保存成功状态的值,有一个reason保存失败状态的值,可以是undefined/thenable/promise。
  • promise只能从pending到rejected, 或者从pending到fulfilled,状态一旦确认,就不会再改变。
  • promise 必须有一个then方法,then接收两个参数,分别是promise成功的回调onFulfilled, 和promise失败的回调onRejected。
  • 如果then中抛出了异常,那么就会把这个异常作为参数,传递给下一个then的失败的回调onRejected。

CustomPromise,还实现不了基本原理的3,4两条,那我们来根据基本原理与Promise/A+分析下,还缺少什么

  • promise有三个状态:pending,fulfilled,rejected。
  • executor执行器调用reject与resolve两个方法
  • 还需要有保存成功或失败两个值的变量
  • then接收两个参数,分别是成功的回调onFulfilled,失败的回调onRejected

那再来改进下CustomPromise

// 定义三个常量表示状态
const PENDING = 'pending';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected';
​
class CustomPromise {
  constructor(executor) {
    executor(this.resolve, this.reject);}
  // resolve和reject为什么要用箭头函数?
  // 如果直接调用的话,普通函数this指向的是window或者undefined
  // 用箭头函数就可以让this指向当前实例对象
  resolve = (value) => {
    this.value = value;};
  reject = (value) => {
    this.reason = value;};
  // 成功之后的值
  value = undefined;
  // 失败之后的值
  reason = undefined;
​
  then(onFulfilled,onRejected) {}
  catch() {}
  finally() {}
} 

那我们根据Promise基本原理看看它原生Promise的效果

new Promise(function (resolve, reject) {
  resolve("成功");
  reject("失败");
}).then((value) => {
    console.log(value); // 结果为‘成功’},(err) => {
    console.log(err);}
);
​
new Promise(function (resolve, reject) {
  reject("失败");
  resolve("成功");
}).then((value) => {
    console.log(value);},(err) => {
    console.log(err); // 结果为‘失败’}
); 

可以看出与基本原理一样的效果,那我们分析下如何实现这种效果

  • 需要控制promise状态
  • 在then方法里要调用成功或失败的回调函数
const PENDING = "pending";
const FULFILLED = "fulfilled";
const REJECTED = "rejected";
​
class CustomPromise {
  constructor(executor) {
    executor(this.resolve, this.reject);}
  // resolve和reject为什么要用箭头函数?
  // 如果直接调用的话,普通函数this指向的是window或者undefined
  // 用箭头函数就可以让this指向当前实例对象
  resolve = (value) => {
    // promise只能从pending到rejected, 或者从pending到fulfilled
    if (this.status == PENDING) {
      this.status = FULFILLED;
      this.value = value;
  }};
  reject = (err) => {
    // promise只能从pending到rejected, 或者从pending到fulfilled
    if (this.status == PENDING) {
      this.status = REJECTED;
      this.reason = err;
  }};
  status = PENDING;
  // 成功之后的值
  value = undefined;
  // 失败之后的值
  reason = undefined;
​
  then(onFulfilled, onRejected) {
    // 需要判断状态,根据状态选择处理回调函数
    if (this.status == FULFILLED) {
      onFulfilled(this.value);
  } else if (this.status == REJECTED) {
      onRejected(this.reason);
  }}
  catch() {}
  finally() {}
} 

来测试下CustomPromise

new CustomPromise(function (resolve, reject) {
  resolve("成功");
  reject("失败");
}).then((value) => {
    console.log(value);// 结果为‘成功’},(err) => {
    console.log(err);}
);
​
new CustomPromise(function (resolve, reject) {
  reject("失败");
  resolve("成功");
}).then((value) => {
    console.log(value);},(err) => {
    console.log(err);// 结果为‘失败’}
);
​ 

Promise.then链式调用

我们都知到Primose.then是可以链式调用的,那我们先看看原生效果

const promise = new Promise((resolve, reject) => {
  resolve("start");
});
promise.then((res) => {
    console.log(res);
    return new Pr
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值