• 如果您觉得本站非常有看点,那么赶紧使用Ctrl+D 收藏吧

经典Promise面试题—-手写Promise详细步骤(三)

互联网 diligentman 5天前 4次浏览

手写Promise封装继续行进—-实现then方法的结构功能!

按照步骤进行,逻辑思路很简单易实现!
前文链接导航:

功能1:搭建Promise结构,实现关键resolve、reject功能
功能2:实现throw抛出异常以及Promise对象状态单次更改功能

本文在前两篇的实现基础上继续封装Promise其他功能
	1then()方法执行回调的实现
  1. 首先:实例化对象中调用then方法
<script src="./Promise.js"></script>
<body>
  <script>
    let p = new Promise((resolve, reject) => {

     // reject('error');
      resolve('OK');
      // 抛出异常
      // throw "error"
    })
    console.log(p)
    // 实例调用then方法
    p.then(value => {
      console.log(value);//成功用log输出
    }, reason => {
      console.warn(reason);//失败用warn输出
    })
  </script>

  1. 注释掉script标签引用,查看内置Promise的表现,明确自定义封装预期结果,结果如下:
//注释掉下列代码,查看内置表现
<script src="./Promise.js"></script>

经典Promise面试题----手写Promise详细步骤(三)

  1. 恢复script标签引入,因为我们没有进行相应的封装,没有调用then方法,所以还不能实现上述功能,由于同步执行,所以需要在Promise.then()方法中调用回调函数,逻辑结构如下:

经典Promise面试题----手写Promise详细步骤(三)
代码结构为:

// 添加then方法
Promise.prototype.then=function(onResolved,onRejectd){
  // 调用回调函数,这里不能直接调用,因为promise的状态是不一定的
  if(){
      // 成功调用onResolved 
    onResolved();
  }
  if(){
      // 失败调用onRejected
    onRejectd();
  }
}
分析判断条件:
我们知道成功和失败的不同状态会回调不同的函数,那么成功和失败的判断条件是什么呢?
	----应该是上述Promise实例对象中声明的PromiseState这个属性(不懂请导航到前两篇文章...

具体代码如下:

// 添加then方法
Promise.prototype.then=function(onResolved,onRejectd){
  // 调用回调函数,这里不能直接调用,因为promise的状态是不一定的
  if(this.PromiseState === 'fulfilled'){
      // 成功调用onResolved 
    onResolved();
  }
  if(this.PromiseState === 'rejected'){
      // 失败调用onRejected
    onRejectd();
  }
}

代码中的this指向问题解释:

   1:then方法是由p这个Promise实例调用的,所以在这个对象中,this就是指向实例对象p的
   2:所以this.PromiseState获取的就是p这个实例的PromiseState属性

4:继续向下发现问题,逻辑关系展示:
经典Promise面试题----手写Promise详细步骤(三)

上图问题描述:
	1:  实例p.then()中的回调函数声明时是有形参的(value或者reason)
	2:   这个函数在调用时是传给了.then()方法中的onResolved实参
	3:但是按照上述代码,调用时并没有给传递相应参数
	4:这个参数是保存了上述状态更改的具体值,也就是之前声明的PromiseResult这个属性
	5:于是继续完善代码如下:
// 添加then方法
Promise.prototype.then=function(onResolved,onRejectd){
  // 调用回调函数,这里不能直接调用,因为promise的状态是不一定的
  if(this.PromiseState === 'fulfilled'){
      // 成功调用onResolved 
    onResolved(this.PromiseResult);
  }
  if(this.PromiseState === 'rejected'){
      // 失败调用onRejected
    onRejectd(this.PromiseReslut);
  }
}

逻辑分析:
经典Promise面试题----手写Promise详细步骤(三)
代码执行结果:

当然可以验证reject 以及 throw 改变promise状态,同时调用.then方法,这里暂不展示,大家可以自行验证。

经典Promise面试题----手写Promise详细步骤(三)
至此,我们队then方法中回调的执行有了一个完整的实现!但是…

注意:
	1:以上三节代码都是执行器中的函数为同步执行,即通过resolve('  OK '),直接改变Promise对象的状态,而不是异步改变的。
	2:在接下来的封装中,考虑执行器中使用异步方式 :
	 	let p = new Promise((resolve, reject) => {
     		 // 执行器中异步执行改变状态
     		 setTimeout(()=>{
       			 resolve('OK');
    		  },1000)
	     // 执行器中同步执行改变状态
	      // reject('error');
	      // resolve('OK');
	      // 抛出异常
	      // throw "error"
    })
    3:使用setTimeout()也只是用定时器做一个模拟,方便实现
      而在实际中,可能是一个文件的IO,数据库的IO,也可能是一个网络请求的IO,
      总之是异步的,并不是立刻改变对象状态的
    4:对于这种异步的,要求也是能够成功执行回调的,显然我们目前封装的代码还不可以实现。
    

总结:这里放上截止目前手写Promise的完整代码,包含以往三部分的全部功能,如下:

全部功能:
	1:搭建自定义Promise结构,实现关键resolve、reject功能。
	2:实现throw抛出异常改变对象状态
	3:确保Promise对象状态只能更改一次
	4:实现关键then方法的调用功能
index.html中全部代码:
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Promise封装</title>
</head>
<script src="./Promise.js"></script>
<body>
  <script>
    let p = new Promise((resolve, reject) => {
      // 执行器中异步执行改变状态
      setTimeout(()=>{
        resolve('OK');
      },1000)
      // 执行器中同步执行改变状态
      // reject('error');
      // resolve('OK');
      // 抛出异常
      // throw "error"
    })
    // console.log(p)
    // 实例调用then方法
    p.then(value => {
      console.log(value);//成功用log输出
    }, reason => {
      console.warn(reason);//失败用warn输出
    })
  </script>
</body>
</html>
Promise.js中全部代码:
// 声明构造函数
function Promise(executor){
  // 添加属性,以便下面修改
  this.PromiseState="pendding";
  this.PromiseResult=null;
  // 保存实例对象的 this 的值
  const self=this;
  // resolve函数
  function resolve(data){
    // 判断状态
    if(self.PromiseState !== 'pendding') return;
    // 1.修改对象的状态
    self.PromiseState="fulfilled";//和resolved一样的含义,都表示成功
    // 2.设置对象的结果值
    self.PromiseResult=data;
  }
  // reject函数
  function reject(data){
    // 判断状态
    if(self.PromiseState !== 'pendding') return;
    // 1.修改对象的状态
    self.PromiseState="rejected";
    // 2.设置对象的结果值
    self.PromiseResult=data;
  }
  try{
    // 同步调用 -- 执行器函数
    executor(resolve,reject);
  }catch(err){
    // 修改 promise 对象的状态为失败
    reject(err);
  }
}

// 添加then方法
Promise.prototype.then=function(onResolved,onRejectd){
  // 调用回调函数,这里不能直接调用,因为promise的状态是不一定的
  if(this.PromiseState === 'fulfilled'){
      // 成功调用onResolved 
    onResolved(this.PromiseResult);
  }
  if(this.PromiseState === 'rejected'){
      // 失败调用onRejected
    onRejectd(this.PromiseReslut);
  }
}

对应的代码在每一个小节中都有详细的介绍,务必注意搞清逻辑关系,实现起来就会很灵活轻松! 后续异步执行功能继续更新封装,敬请期待,感谢观看!


程序员灯塔
转载请注明原文链接:经典Promise面试题—-手写Promise详细步骤(三)
喜欢 (0)