zoukankan      html  css  js  c++  java
  • Promise的封装

    要封装Promise,首先要了解Promise的使用。

    Promise有以下几个特点:1、Promise是一个构造函数 2、实例化Promise时有两个回调函数,resolve,reject ,成功执行resolve,失败执行reject

    3、在实例化p的then中有两个对应的回调函数,第一个回调是resolve执行时触发,第二个回调是reject执行时触发4、语法糖catch,就是执行reject的时候,不调用第二个参数,直接链式写catch,像用then一样【 有坑,异步调用resolve,reject不会触发 】5、p.then()是Promise类型,p.catch()是Promise类型

    先来个简单的使用实例:

    //  使用resolve
    let p = new Promise((resolve,reject)=>{ setTimeout(()=> { console.log('延时器代码执行') // 执行成功 resolve('执行成功') },1000) }) p.then(res=>{ console.log(res) //执行成功 })
    //  使用reject
    let p = new Promise((resolve,reject)=>{ setTimeout((res)=> { // 模拟执行出错 if(!res){ // 没有给res传参 return reject('执行出错,没有参数') } console.log('延时器代码执行') },1000) }) p.then(res => { console.log(res) //执行成功 },error => { console.log(error) //'执行出错,没有参数' 执行出错执行
        })

    封装同步的Promise

     function myPromise(callback) { //callback 代表( resolve,reject ) => {}
            // 默认状态pending,首先没有执行成功或失败函数之前状态是pending
            (this.promiseStatus = 'pending'), this.msg;
         // 用that存当前this的内容 let that
    = this // new 自动执行 , 调用callback callback(
          // 定义resolve
    function() { // 这里面的arguments,this都是坑,他们两个都是坑人大咖,两个都是不定值 that.promiseStatus = 'resolved'; // resolve 的第一个实参 that.msg = arguments[0]; },
           // 定义reject
    function() { that.promiseStatus = 'rejected'; // rejected 的第一个实参 that.msg = arguments[0]; } ); } // 往myPromise 原型上添加then方法 myPromise.prototype.then = function() { // 这里的this就是让实例调用,指向实例的,并不是指向构造函数!!! 花式秀this if (this.promiseStatus == 'resolved') { arguments[0](this.msg); } else if (this.promiseStatus == 'rejected') { arguments[1](this.msg); } }; // 实例化 const p = new myPromise((resolve, reject) => { reject('失败') }); // 使用then p.then( function (res) { console.log(res); }, function (err) { console.log(err); } );

    代码的思路我会尽量写详细写,以及一些容易出错的地方,想了几个小时才发现。。。。。。(无地自容)

      arguments和this值得分析分析。首先是arguments,一开始想省事直接谢了()=>{}代替function(){},乖乖,好了,接下来的1个小时就是找bug时间,()=>{ this.promiseStatus;this.msg = arguments[0] } 请大家尽情笑话我,当时没有意识到箭头函数的this是指向上层的this,且不变的,由于arguments和this一样有不确定性,所以也是指向上层,所以一直纠结为什么arguments不是箭头函数()=>{ this.promiseStatus;this.msg = arguments[0] } 中 ()里的实参,而是一直是callback ,所以还是老老实实换成function(){this.promiseStatus;this.msg = arguments[0]}

      this引出的2个小时的挠头疯狂:刚开始并没有发现是this的问题,而是封装完了,运行的时候,不管我在实例里调用resolve还是reject都没有打印效果,p.then()调用也没问题,然后找了then方法的定义位置,没错啊,上面callback定义的两个resolve,reject实参函数体我也各自修改了状态,单词也没写错,1个多小时过后我终于想看看是不是状态没改变,导致then定义方法里的if没执行,果然不管在实例的时候调用resolve还是reject,状态都是pending,没变过,没道理啊,我眼花了?我继续往上找,我忽然想起了刚才的argument,忽然面色暗淡,用颤抖的双手打印了function(){}里的this,呵,window。也就是根本就没变过实例里的promiseStatus属性,所以用that存下当前的this,值得一提的是用箭头函数this就不用that存了,原因在上一段,但是arguments必须又要function(){  }的形式......

    异步执行resolve,reject

    function myPromise(callback) { //callback 代表( resolve,reject ) => {}
            // 默认状态pending,首先没有执行成功或失败函数之前状态是pending
            this.promiseStatus = 'pending',
            this.status = [],  //异步时起作用
            this.msg;
         // 用that存当前this的内容
            let that = this
            // new 自动执行 , 调用callback
            callback(
          // 定义resolve
              function() {
                that.promiseStatus = 'resolved';
                // resolve 的第一个实参
                that.msg = arguments[0];
                //判断存不存在resolve方法  {  } 
                for (const {resolve} of that.status) {
                    resolve(that.msg)
                }
              },
           // 定义reject
              function() {
                that.promiseStatus = 'rejected';
                // rejected 的第一个实参
                that.msg = arguments[0];
                for (const {reject} of that.status) {
                    reject(that.msg)
                }
              }
            );
          }
          // 往myPromise 原型上添加then方法
          myPromise.prototype.then = function() {
            // 这里的this就是让实例调用,指向实例的,并不是指向构造函数!!! 花式秀this
            if (this.promiseStatus == 'resolved') {
              arguments[0](this.msg);
              console.log('1234');
              
            } else if (this.promiseStatus == 'rejected') {
              arguments[1](this.msg);
            }else{
                this.status.push({ resolve:arguments[0],reject:arguments[1] })  //实例参数有异步语句的会先执行then
                console.log('yyy');
            }
          };
          // 实例化
    
          //对于实例化的异步我个人理解为new的过程是这样的,首先打印123是同步的setTimeout本身是同步的,里面的回调是异步的,是异步就给我等等,先执行then(),由于是自己封装的then()
        是以原型方法存在,同步调用,调用以后status就变成了[
    { resolve:arguments[0],reject:arguments[1] }],然后回过头执行setTimeout里的reject,这时候status有了reject
    a 所以可以调用then里面的两个回调也就拿到参数:这里我想了好久。终于想明白了 同步then里面两个回调是在then中执行,异步是在定义构造函数的callback中的第一个或第二个参数定义中执行。
          //所以在构造函数callback()已经完成,此时还没运行异步的reject或reject,因为只是声明函数未执行,当调用
          const p = new myPromise((resolve, reject) => {
              setTimeout(reject,100,'调用失败')
              console.log(123)
          });
          // 使用then
          p.then(
           function (res) {
             console.log(res); 
           },
           function (err) {
             console.log(err);
           }
          );

    有一个问题想了很久,在异步执行resove或reject的时候,setTimeout(   )会不会执行?是先执行setTimeout(   )再执行then还是先执行then,回过头来执行setTimeout,事实上是先执行then的。紧接着then调用了一次,而那一次由于异步调用所以运行this.status.push({ resolve:arguments[0],reject:arguments[1] }),然后执行异步的reject没错。但是这时候还要执行一次then吗?不执行的话,then里面两个参数没法调用,只是声明,执行的话就执行两次then有点说不过去

    因为问题想了很久,后来才发现很简单。所以要回顾一下

    这里主要说的是异步执行resolve,reject,同步和上面没区别,也用不到status。

    其实把还是在执行顺序的问题上。首先执行new的操作,直接进入构造函数执行一遍,接着看到了异步操作和同步操作,先执行同步的打印123没话讲,异步操作呆一边去先。往下走执行then( )然后这一步因为new中异步执行reject(以代码来说),所以status就有了一个[{reject:arguments[1]}],此时再去执行new中的reject函数就会执行(不要误以为执行setTimeout,是里面的回调是异步的)callback对应的第二个参数(函数体),在第二个函数体中for (const {reject} of that.status) {reject(that.msg)}  给then里的第二个参数(也是函数体)传了实参,所以才能打印出来。

    归根结底   同步执行then的两个函数参数是在原型中的then方法定义中。

         异步执行then的两个函数参数是在构造函数callback的两个函数参数中。

  • 相关阅读:
    centos7 修复引导
    Django 过滤器
    Django 面向对象orm
    Django models字段查询谓词表
    linux常用的监控命令
    常用SQL语句
    python实现FTP服务器
    用python做一个图片验证码
    rsync
    jsonp的理解
  • 原文地址:https://www.cnblogs.com/wchjdnh/p/10859938.html
Copyright © 2011-2022 走看看