Promise原理分析及简单实现

前端日记

今天是前端日记的第五天,清楚了promise的使用后,接下来我们开始分析promise的原理以及做简单的实现,然后与大家一起分享。一个前端小白的学习之路。

promise分析

先上代码,实例化一个promise

var promise = new Promise(function (resolve, reject) {
    //做一些异步操作
    setTimeout(function () {
      var num = parseInt(Math.random() * 10); //生成1-10的随机数
      if (num <= 5) {
        resolve(num);
      } else {
        reject(`数字太大了,我拿到了${num}`);
      }
    }, 2000);
  });

从代码上看,Promise这个类中传一个函数作为参数,把这个参数的函数称为callback,并且这个callback函数是马上执行的,也就是在new Promise这个类的时候自动执行下面这个callback函数

function (resolve, reject) {
    //做一些异步操作
    setTimeout(function () {
      var num = parseInt(Math.random() * 10); //生成1-10的随机数
      if (num <= 5) {
        resolve(num);
      } else {
        reject(`数字太大了,我拿到了${num}`);
      }
    }, 2000);
  }

再看这个函数又有2个函数参数,分别是Promise的resolve()和 reject()方法,作用是让Promise的状态定型,那么我们思考如何马上执行callback函数并把resolve和reject方法以参数的形式传给callback函数,结合promise的介绍,我们可以先初步实现一个promise类

class Mpromise {
  constructor(callback) {
    this.resolveVal = undefined;//存放成功的值
    this.rejectVal = undefined;//存放失败的值
    this.status = "pending"; //默认是等待状态
    //初始化时马上执行callback函数并把resolve和reject方法以参数的形式传递
    try {
      callback(this.resolve.bind(this), this.reject.bind(this));
    } catch (error) {
      this.reject(error);
    }
  }
  resolve(val) {
  //如果状态不是等待中则不做任何操作
    if (this.status === "pending") {
      this.resolveVal = val;
      this.status = "resolve";
    }
  }

  reject(val) {
  //如果状态不是等待中则不做任何操作
    if (this.status === "pending") {
      this.rejectVal = val;
      this.status = "reject";
    }
  }
 }

是否有人好奇,this.resolve.bind(this)为什么要使用bind(this),是因为在callback函数内部resolve和reject的this指向window这个而不是promise所以要改变下this的指向否则会报错
在这里插入图片描述

promise.then分析

接下来就是要实现then方法,老规矩先观察

promise.then(function(successDate){
  console.log(successDate)
 },function(errorData){
  console.log(errorData)
 })

可以看到,then方法中是有2个参数分别是成功后的回调和失败后的回调,那么其实也很好实现,直接判断状态,执行相应回调就OK,先写个同步版的

//同步版的then方法
 then(successFn, failFn) {
    let self = this;
    if (self.status === "pending") {
      return;//没有成功也没有失败就不做处理
      } else if (self.status === "resolve") {
        successFn(self.resolveVal);
      } else {
        failFn(self.rejectVal);
      }
  }

var a1 = new Mpromise(function (resolve, reject) {
  resolve("成功数据1");
});
a1.then(function(success){
  console.log(success) //输出成功数据1
})

以上代码不难理解,当new promise的时候马上执行resolve方法,此时promise的状态已经固定为resolve,然后执行then方法把成功的值返回给回调函数,但是同步的往往不是我们所需要的,我们需要的是then能返回2秒(2秒只是个代词,代表异步的时间)后的结果,直接上全代码

class Mpromise {
  constructor(callback) {
    this.resolveVal = undefined;
    this.rejectVal = undefined;
    this.status = "pending"; //默认是等待状态
    this.resolveList = [];//成功回调数组
    this.rejectList = [];//失败回调数组

    // callback(self.success, self.fail);

    //初始化时马上执行callback
    try {
      callback(this.success.bind(this), this.fail.bind(this));
    } catch (error) {
      this.fail(error);
    }
  }

  success(val) {
    if (this.status === "pending") {
      this.resolveVal = val;
      this.status = "resolve";
      this.resolveList.length &&
        this.resolveList.forEach((fn) => {
          fn(this.resolveVal);
        });
    }
  }

  fail(val) {
    if (this.status === "pending") {
      this.rejectVal = val;
      this.status = "reject";
      this.rejectList.length &&
        this.rejectList.forEach((fn) => {
          fn(this.rejectVal);
        });
    }
  }

  isFunction(obj) {
    return "function" === typeof obj;
  }


  then(successFn, failFn) {
   let self = this;
   if (self.status === "pending") {
        self.isFunction(successFn) && self.resolveList.push(successFn);//添加到resolveList数组中
        self.isFunction(failFn) && self.rejectList.push(failFn);//添加到rejectList数组中
      } else if (self.status === "resolve") {
        successFn(self.resolveVal);
      } else {
        failFn(self.rejectVal);
      }
  }
  retun this;//链式调用
}

var a1 = new Mpromise(function (resolve, reject) {
  setTimeout(() => {
    resolve("成功数据1");
  }, 5000);
});

a1.then(function (successDate) {
  console.log(`监听到的数据是1:${successDate}`);
})
  .then(function (successDate) {
    console.log(`监听到的数据是2:${successDate}`);
  })
  .then(function (successDate) {
    console.log(`监听到的成功数据是3:${successDate}`);
  });

考虑到异步的情况,我们要采用队列的形式定义2个数组resolveList 和 rejectList 用来存储成功或失败后的回调,看代码,a1在创建完就马上执行then()方法,然后把回调函数添加到resolveList 中存储, 5秒后执行success函数,在把队列中的回调函数逐个拿出来调用,应此这里的返回的值应该是
在这里插入图片描述
但是,promise的函数远不止链式调用自身,因为这样没什么意义,根据es6中promise的描述
下一章试着实现 then的链式调用。
谢谢观赏,如有不足,请下方留言,共勉之! —一个菜鸡前端的路程

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

会跳舞的鸡

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值