资讯专栏INFORMATION COLUMN

浅谈Promise之参照Promise/A+规范实现Promise类

roundstones / 604人阅读

摘要:在需要多个操作的时候,会导致多个回调函数嵌套,导致代码不够直观,就是常说的回调地狱,通常通过来解决本意是承诺,在程序中的意思就是承诺我过一段时间后会给你一个结果。

在需要多个操作的时候,会导致多个回调函数嵌套,导致代码不够直观,就是常说的回调地狱,通常通过promise来解决

Promise本意是承诺,在程序中的意思就是承诺我过一段时间后会给你一个结果。 什么时候会用到过一段时间?答案是异步操作,异步是指可能比较长时间才有结果的才做,例如网络请求、读取本地文件等

按照Promise/A+规范来实现一个Promise类
构造函数初始化逻辑
const PENDING =  "pending";//初始态
const FULFILLED =  "fulfilled";//初始态
const REJECTED =  "rejected";//初始态
let self = this;//先缓存当前promise实例
self.status = PENDING;//设置状态
self.onResolvedCallbacks = [];//定义存放成功的回调的数组
self.onRejectedCallbacks = []; //定义存放失败回调的数组
executor执行器,包含两个参数,分别是resolve 解决和reject 拒绝,new Promise这个executor就会执行

Promise有三个状态:初始化状态为pending,成功状态为fulfilled,失败状态rejected,如果代码一旦成功就不会走向失败,若 一直pending 永远不给你明确的答复

当调用以下方法的时候,如果promise状态为pending的话可以转成成功态,如果已经是成功态或者失败态了,则什么都不做

  function resolve(value){ 
    if(value!=null &&value.then&&typeof value.then == "function"){
      return value.then(resolve,reject);
    }
    setTimeout(function(){
      if(self.status == PENDING){
        self.status = FULFILLED;
        self.value = value;
        self.onResolvedCallbacks.forEach(cb=>cb(self.value));
      }
    })
  }
  function reject(reason){ //2.1.2
    setTimeout(function(){
      if(self.status == PENDING){
        self.status = REJECTED;
        self.value = reason;
        self.onRejectedCallbacks.forEach(cb=>cb(self.value));
      }
    });
  }
}
因为此函数执行可能会异常,所以需要捕获,如果出错了,需要用错误对象reject,如果这函数执行失败了,则用失败的原因reject这个promise,需要用try...catch(e)...进行处理
  try{
    executor(resolve,reject);
  }catch(e){
    reject(e);
  };
Promise的解析过程
function resolvePromise(promise2,x,resolve,reject){
  if(promise2 === x){
    return reject(new TypeError("循环引用"));
  }
  let called = false;
  if(x instanceof Promise){
    if(x.status == PENDING){
      x.then(function(y){
        resolvePromise(promise2,y,resolve,reject);
      },reject);
    }else{
      x.then(resolve,reject);
    }
  }else if(x!= null &&((typeof x=="object")||(typeof x == "function"))){
   try{
     let then = x.then;
     if(typeof then == "function"){
       then.call(x,function(y){
          if(called)return;
          called = true;
          resolvePromise(promise2,y,resolve,reject)
       },function(err){
         if(called)return;
         called = true;
         reject(err);
       });
     }else{
       resolve(x);
     }
   }catch(e){
     if(called)return;
     called = true;
     reject(e);
   }
  }else{
    resolve(x);
  }
}
then方法就是用来指定Promise 对象的状态改变时确定执行的操作,resolve 时执行第一个函数(onFulfilled),reject 时执行第二个函数(onRejected)
此方法中,如果成功和失败的回调没有传,则表示这个then没有任何逻辑,只会把值往后抛
Promise.prototype.then = function(onFulfilled,onRejected){
  onFulfilled = typeof onFulfilled == "function"?onFulfilled:function(value){return  value};
  onRejected = typeof onRejected == "function"?onRejected:reason=>{throw reason};
  let self = this;
  let promise2;
  if(self.status == FULFILLED){
    return promise2 = new Promise(function(resolve,reject){
      setTimeout(function(){
        try{
          let x =onFulfilled(self.value);
          resolvePromise(promise2,x,resolve,reject);
        }catch(e){
          reject(e);
        }
      })
    });
  }
  if(self.status == REJECTED){
    return promise2 = new Promise(function(resolve,reject){
      setTimeout(function(){
        try{
          let x =onRejected(self.value);
          resolvePromise(promise2,x,resolve,reject);
        }catch(e){
          reject(e);
        }
      })
    });
  }
  if(self.status == PENDING){
   return promise2 = new Promise(function(resolve,reject){
     self.onResolvedCallbacks.push(function(){
         try{
           let x =onFulfilled(self.value);
           resolvePromise(promise2,x,resolve,reject);
         }catch(e){
           reject(e);
         }
     });
     self.onRejectedCallbacks.push(function(){
         try{
           let x =onRejected(self.value);
           resolvePromise(promise2,x,resolve,reject);
         }catch(e){
           reject(e);
         }
     });
   });
  }
}
promise的链式调用

每次调用返回的都是一个新的Promise实例

链式调用的参数通过返回值传递:即会将第一个then成功后,将他的返回值作为下一次成功的回调函数的参数

then可以使用链式调用的写法原因在于,每一次执行该方法时总是会返回一个Promise对象

catch 只是 promise.then(undefined, onRejected); 方法的一个别名而已。 也就是说,这个方法用来注册当promise对象状态变为Rejected时的回调函数
catch原理就是只传失败的回调
Promise.prototype.catch = function(onRejected){
  this.then(null,onRejected);
}
Promise.all 接收一个 promise对象的数组作为参数,当这个数组里的所有promise对象全部变为resolve或reject状态的时候,它才会去调用 .then 方法
Promise.all = function(promises){
 return new Promise(function(resolve,reject){
   let done = gen(promises.length,resolve);
   for(let i=0;i
Promise.race只要有一个promise对象进入 FulFilled 或者 Rejected 状态的话,就会继续进行后面的处理
Promise.race = function(promises){
  return new Promise(function(resolve,reject){
    for(let i=0;i
别人提供 给你一个方法,需要你传入一个promise,但你只有一个普通的值,你就可以通过这个方法把这个普通的值(string number object)转成一个promise对象
返回一个立刻成功的promise
Promise.resolve = function(value){
  return new Promise(function(resolve){
    resolve(value);
  });
}
返回一个立刻失败的promise
Promise.reject = function(reason){
  return new Promise(function(resolve,reject){
    reject(reason);
  });
}

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/92494.html

相关文章

  • 3行代码实现一个简易版promise

    前言 作为一个后端过来的同学,刚入门前端的时候,被js种种「反人类」的概念折腾的死去活来的.其中一个印象比较深刻的,就是promise,感觉实在太难理解了...所有就有了写个简单的promise的想法.希望能帮助到一些跟我一样,感觉promise很难理解的新同学. promise的教程网上多如牛毛,其中写的比较通俗易懂的莫过于阮一峰的es6,反正我是他的书才懂的.所以今天,我们也不会来复述一遍如何...

    ralap 评论0 收藏0
  • 浅谈Javascript中Promise对象的实现

    摘要:我们可以进行适当的改进,把回调函数写到外面即使是改写成这样,代码还是不够直观,但是如果有了对象,代码就可以写得非常清晰,一目了然,请看这样函数就不用写在的回调中了目前的标准中还未支持对象,那么我们就自己动手,丰衣足食吧。 本文同步自我得博客:http://www.joeray61.com 很多做前端的朋友应该都听说过Promise(或者Deferred)对象,今天我就讲一下我对Prom...

    caiyongji 评论0 收藏0
  • 浅谈ES6原生Promise

    摘要:如果有错误,则到的第二个回调函数中,对错误进行处理。假设第一个的第一个回调没有返回一个对象,那么第二个的调用者还是原来的对象,只不过其的值变成了第一个中第一个回调函数的返回值。 ES6标准出炉之前,一个幽灵,回调的幽灵,游荡在JavaScript世界。 正所谓: 世界本没有回调,写的人多了,也就有了})})})})})。 Promise的兴起,是因为异步方法调用中,往往会出现回调函数一...

    yedf 评论0 收藏0
  • JavaScript Promise启示录

    摘要:近几年随着开发模式的逐渐成熟,规范顺势而生,其中就包括提出了规范,完全改变了异步编程的写法,让异步编程变得十分的易于理解。最后,是如此的优雅但也只是解决了回调的深层嵌套的问题,真正简化异步编程的还是,在端,建议考虑。 本篇,简单实现一个promise,主要普及promise的用法。 一直以来,JavaScript处理异步都是以callback的方式,在前端开发领域callback机制...

    Juven 评论0 收藏0
  • [转载·JS] JavaScript Promise启示录

    摘要:近几年随着开发模式的逐渐成熟,规范顺势而生,其中就包括提出了规范,完全改变了异步编程的写法,让异步编程变得十分的易于理解。最后,是如此的优雅但也只是解决了回调的深层嵌套的问题,真正简化异步编程的还是,在端,建议考虑。 前段时间频频看到Promise这个词,今天发现腾讯AlloyTeam写得这篇很赞,遂转之。 原文链接 本篇,主要普及promise的用法。 一直以来,JavaScrip...

    Lyux 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<