摘要:在需要多个操作的时候,会导致多个回调函数嵌套,导致代码不够直观,就是常说的回调地狱,通常通过来解决本意是承诺,在程序中的意思就是承诺我过一段时间后会给你一个结果。
在需要多个操作的时候,会导致多个回调函数嵌套,导致代码不够直观,就是常说的回调地狱,通常通过promise来解决按照Promise/A+规范来实现一个Promise类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对象
返回一个立刻成功的promisePromise.resolve = function(value){ return new Promise(function(resolve){ resolve(value); }); }返回一个立刻失败的promisePromise.reject = function(reason){ return new Promise(function(resolve,reject){ reject(reason); }); }
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/92494.html
前言 作为一个后端过来的同学,刚入门前端的时候,被js种种「反人类」的概念折腾的死去活来的.其中一个印象比较深刻的,就是promise,感觉实在太难理解了...所有就有了写个简单的promise的想法.希望能帮助到一些跟我一样,感觉promise很难理解的新同学. promise的教程网上多如牛毛,其中写的比较通俗易懂的莫过于阮一峰的es6,反正我是他的书才懂的.所以今天,我们也不会来复述一遍如何...
摘要:我们可以进行适当的改进,把回调函数写到外面即使是改写成这样,代码还是不够直观,但是如果有了对象,代码就可以写得非常清晰,一目了然,请看这样函数就不用写在的回调中了目前的标准中还未支持对象,那么我们就自己动手,丰衣足食吧。 本文同步自我得博客:http://www.joeray61.com 很多做前端的朋友应该都听说过Promise(或者Deferred)对象,今天我就讲一下我对Prom...
摘要:如果有错误,则到的第二个回调函数中,对错误进行处理。假设第一个的第一个回调没有返回一个对象,那么第二个的调用者还是原来的对象,只不过其的值变成了第一个中第一个回调函数的返回值。 ES6标准出炉之前,一个幽灵,回调的幽灵,游荡在JavaScript世界。 正所谓: 世界本没有回调,写的人多了,也就有了})})})})})。 Promise的兴起,是因为异步方法调用中,往往会出现回调函数一...
摘要:近几年随着开发模式的逐渐成熟,规范顺势而生,其中就包括提出了规范,完全改变了异步编程的写法,让异步编程变得十分的易于理解。最后,是如此的优雅但也只是解决了回调的深层嵌套的问题,真正简化异步编程的还是,在端,建议考虑。 本篇,简单实现一个promise,主要普及promise的用法。 一直以来,JavaScript处理异步都是以callback的方式,在前端开发领域callback机制...
摘要:近几年随着开发模式的逐渐成熟,规范顺势而生,其中就包括提出了规范,完全改变了异步编程的写法,让异步编程变得十分的易于理解。最后,是如此的优雅但也只是解决了回调的深层嵌套的问题,真正简化异步编程的还是,在端,建议考虑。 前段时间频频看到Promise这个词,今天发现腾讯AlloyTeam写得这篇很赞,遂转之。 原文链接 本篇,主要普及promise的用法。 一直以来,JavaScrip...
阅读 2746·2021-11-16 11:45
阅读 1653·2021-09-26 10:19
阅读 2050·2021-09-13 10:28
阅读 2802·2021-09-08 10:46
阅读 1528·2021-09-07 10:13
阅读 1524·2019-08-30 13:50
阅读 1373·2019-08-30 11:17
阅读 1454·2019-08-29 13:18