写点什么

【前端】一文彻底学会 Promise

  • 2022 年 1 月 13 日
  • 本文字数:3769 字

    阅读完需:约 12 分钟

作者:D827

来源:恒生LIGHT云社区


没有一个功能是看了源码后,还不会用的。所以看完本篇文章,希望能帮助你彻底掌握 Promise。

Promise 的介绍

Promise 对象是 ES6 提供的实现异步的一个解决方案,它使得异步方法可以像同步方法那样返回值。


promise 是一个构造函数包裹(封装)一个异步函数(ajax;定时器;数据库读取;fs 文件读取),当然它也可以包裹一个非异步函数。入参为两个函数resolve、reject。成功调用 resolve,并传递参数,失败调用 reject,并传递参数。使用.then 来作为回调结果的处理,then 接受两个函数参数,第一个参数接受正确的返回结果,第二个函数接收错误的返回结果。


Promise 三种状态:pending、fullfilled/resolved、rejected


Promise 初始状态为 pending,通过 resolve 方法将状态修改为 fullfilled/resolved;通过 reject 将状态修改为 rejected


promise 的优点:它能够实现链式调用,解决了回调实现异步导致的回调地狱问题。


promise 的缺点:


  1. 无法监测进行状态、新建立即执行且无法取消;

  2. 如果不设置回调函数,Promise 内部抛出的错误,不会反应到外部;

  3. 有时会造成多个 then 的链式调用,可能会造成代码的语义不够明确。

Promise 的基本使用

function sleep(data){    return new Promise((resolve,reject)=>{    // new Promise 包裹的可以是一个异步的代码,也可以是一个同步的代码    // 代码执行成功        setTimeOut(()=>{             let result = null            if(1){              resolve(result)              }else{               reject(result)             }         },1000)})}sleep(1000).then(v=>{    // 正确返回处理},e=>{   // 错误返回处理}).then(v=>{  }).then(v=>{  })…….catch(e=>{    // 错误处理})
复制代码

自定义 Promise 需要注意的问题,及解答

  1. promise 如何修改状态

  2. 通过调用 resolve、reject 修改状态

  3. 多次调用 resolve、reject 可以修改状态吗

  4. 不可以,当从 pending 修改为 resolved 或者 rejected 后无法再次修改为其他状态

  5. promise 是先修改状态还是显示执行 then,以及什么时候得到数据

  6. 两种情况都可能出现,当 promise 包裹的内容为异步时先指定 then 再修改状态,反之先修改状态再执行 then;

  7. 数据是在执行完回调后获取。

  8. promise.then 返回一个 promise,这个返回的类型结果由谁决定

  9. 返回的为 promise,由返回的 promise 决定

  10. 返回为非 promise,则返回为 resolved

  11. promise 如何串联多个操作任务

  12. 因为 promise.then 返回的是一个新的 Promise 对象,所以还可以调用 then,实现链式调用

  13. promise 异常穿透

  14. 意思是不论有多少个 then,中间任意一个 then 出现报错都会被 catch 捕获

  15. 如何终止 promise 链

  16. then 中任意一个出现异常;

  17. 在任意 then 中将 promise 的状态改为 pending。

Promise 的自定义

 //声明构造函数 function Promise(executor){     //添加属性     this.PromiseState = 'pending';     this.PromiseResult = null;     //声明属性 回调存在多个情况     this.callbacks = [];     //保存实例对象的 this 的值     const self = this;// self _this that     //resolve 函数     function resolve(data){         //判断状态 多次调用resolve、reject不可以修改状态         if(self.PromiseState !== 'pending') return;         //1. 修改对象的状态 (promiseState)         self.PromiseState = 'fulfilled';// resolved         //2. 设置对象结果值 (promiseResult)         self.PromiseResult = data;         //调用成功的回调函数         setTimeout(() => {             self.callbacks.forEach(item => {                 item.onResolved(data);             });         });     }     //reject 函数     function reject(data){         //判断状态         if(self.PromiseState !== 'pending') return;         //1. 修改对象的状态 (promiseState)         self.PromiseState = 'rejected';//          //2. 设置对象结果值 (promiseResult)         self.PromiseResult = data;         //执行失败的回调         setTimeout(() => {             self.callbacks.forEach(item => {                 item.onRejected(data);             });         });     }     try{         //同步调用『执行器函数』         executor(resolve, reject);     }catch(e){         //修改 promise 对象状态为『失败』         reject(e);     } }  //添加 then 方法 Promise.prototype.then = function(onResolved, onRejected){     const self = this;     //判断回调函数参数     if(typeof onRejected !== 'function'){         onRejected = reason => {             throw reason;         }     }     if(typeof onResolved !== 'function'){         onResolved = value => value;         //value => { return value};     }     return new Promise((resolve, reject) => {         //封装函数         function callback(type){             try{                 //获取回调函数的执行结果                 let result = type(self.PromiseResult);                 //判断                 if(result instanceof Promise){                     //如果是 Promise 类型的对象                     result.then(v => {                         resolve(v);                     }, r=>{                         reject(r);                     })                 }else{                     //结果的对象状态为『成功』                     resolve(result);                 }             }catch(e){                 reject(e);             }         }         //调用回调函数  PromiseState         if(this.PromiseState === 'fulfilled'){             setTimeout(() => {                 callback(onResolved);             });         }         if(this.PromiseState === 'rejected'){             setTimeout(() => {                 callback(onRejected);             });         }         //判断 pending 状态         if(this.PromiseState === 'pending'){             // 异步情况下保存回调函数 在异步执行结束后执行回调函数             this.callbacks.push({                 onResolved: function(){                     callback(onResolved);                 },                 onRejected: function(){                     callback(onRejected);                 }             });         }     }) }  //添加 catch 方法 Promise.prototype.catch = function(onRejected){     return this.then(undefined, onRejected); }  //添加 resolve 方法 Promise.resolve = function(value){     //返回promise对象     return new Promise((resolve, reject) => {         if(value instanceof Promise){             value.then(v=>{                 resolve(v);             }, r=>{                 reject(r);             })         }else{             //状态设置为成功             resolve(value);         }     }); }  //添加 reject 方法 Promise.reject = function(reason){     return new Promise((resolve, reject)=>{         reject(reason);     }); }  //添加 all 方法 Promise.all = function(promises){     //返回结果为promise对象     return new Promise((resolve, reject) => {         //声明变量         let count = 0;         let arr = [];         //遍历         for(let i=0;i<promises.length;i++){             //             promises[i].then(v => {                 //得知对象的状态是成功                 //每个promise对象 都成功                 count++;                 //将当前promise对象成功的结果 存入到数组中                 arr[i] = v;                 //判断                 if(count === promises.length){                     //修改状态                     resolve(arr);                 }             }, r => {                 reject(r);             });         }     }); }  //添加 race 方法 Promise.race = function(promises){     return new Promise((resolve, reject) => {         for(let i=0;i<promises.length;i++){             promises[i].then(v => {                 //修改返回对象的状态为 『成功』                 resolve(v);             },r=>{                 //修改返回对象的状态为 『失败』                 reject(r);             })         }     }); }
复制代码


希望以上内容对你有所帮助!




想向技术大佬们多多取经?开发中遇到的问题何处探讨?如何获取金融科技海量资源?


恒生LIGHT云社区,由恒生电子搭建的金融科技专业社区平台,分享实用技术干货、资源数据、金融科技行业趋势,拥抱所有金融开发者。


扫描下方小程序二维码,加入我们!



发布于: 刚刚阅读数: 2
用户头像

还未添加个人签名 2018.11.07 加入

还未添加个人简介

评论

发布
暂无评论
【前端】一文彻底学会Promise