作者: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 的缺点:
- 无法监测进行状态、新建立即执行且无法取消; 
- 如果不设置回调函数,Promise 内部抛出的错误,不会反应到外部; 
- 有时会造成多个 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 需要注意的问题,及解答
- promise 如何修改状态 
- 通过调用 resolve、reject 修改状态 
- 多次调用 resolve、reject 可以修改状态吗 
- 不可以,当从 pending 修改为 resolved 或者 rejected 后无法再次修改为其他状态 
- promise 是先修改状态还是显示执行 then,以及什么时候得到数据 
- 两种情况都可能出现,当 promise 包裹的内容为异步时先指定 then 再修改状态,反之先修改状态再执行 then; 
- 数据是在执行完回调后获取。 
- promise.then 返回一个 promise,这个返回的类型结果由谁决定 
- 返回的为 promise,由返回的 promise 决定 
- 返回为非 promise,则返回为 resolved 
- promise 如何串联多个操作任务 
- 因为 promise.then 返回的是一个新的 Promise 对象,所以还可以调用 then,实现链式调用 
- promise 异常穿透 
- 意思是不论有多少个 then,中间任意一个 then 出现报错都会被 catch 捕获 
- 如何终止 promise 链 
- then 中任意一个出现异常; 
- 在任意 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云社区,由恒生电子搭建的金融科技专业社区平台,分享实用技术干货、资源数据、金融科技行业趋势,拥抱所有金融开发者。
扫描下方小程序二维码,加入我们!
评论