在须要多个操做的时候,会致使多个回调函数嵌套,致使代码不够直观,就是常说的回调地狱,一般经过promise来解决数组
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就会执行bash
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的解析过程ui
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没有任何逻辑,只会把值日后抛this
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的链式调用
spa
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);
});
}
复制代码