在需要多个操作的时候,会导致多个回调函数嵌套,导致代码不够直观,就是常说的回调地狱,通常通过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<promises.length;i++){ promises[i].then(function(data){ done(i,data); },reject); } }); }
Promise.race
只要有一个promise对象进入 FulFilled 或者 Rejected 状态的话,就会继续进行后面的处理
Promise.race = function(promises){ return new Promise(function(resolve,reject){ for(let i=0;i<promises.length;i++){ promises[i].then(resolve,reject); } }); }
别人提供 给你一个方法,需要你传入一个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); }); }
注:本文内容来自互联网,旨在为开发者提供分享、交流的平台。如有涉及文章版权等事宜,请你联系站长进行处理。