Promise主要用于異步處理,用來解決傳統(tǒng)的回調(diào)地獄問題。
它是把異步處理規(guī)范起來,采用統(tǒng)一的接口來編寫,使得更規(guī)范化。
在實(shí)際項(xiàng)目中可以用來處理異步函數(shù),以及多個(gè)異步操作的處理,在
異步處理中定義異步方法(如ajax),在.then方法中處理結(jié)果,使得
邏輯更清晰,更易于維護(hù),而不是使用函數(shù)嵌套函數(shù)的方式。
Promise提供了all方法來處理多個(gè)異步程序全部調(diào)用完成后返回結(jié)果,
還提供了與之相對(duì)的race方法.
promise鏈?zhǔn)秸{(diào)用:會(huì)將前一個(gè)then的返回值(return)作為下一次
成功的回調(diào)函數(shù)的參數(shù)。
/**
* 實(shí)現(xiàn)一個(gè)Promise
*/
function Promise(task) {
? ? //接收一個(gè)處理函數(shù)
? ? let that = this;//緩存this
? ? //promise有三種狀態(tài)? 默認(rèn)為pending
? ? that.status = 'pending';
? ? that.onFulfilledFns = [];//所有成功的回調(diào)
? ? that.onRejectedFns = [];//所有失敗的回調(diào)
? ? that.value = undefined;
? ? function resolve(value) {
? ? ? ? //成功函數(shù)
? ? ? ? if(that.status == 'pending'){
? ? ? ? ? ? that.status = 'fulfilled';
? ? ? ? ? ? that.value = value;
? ? ? ? ? ? //執(zhí)行所有成功的回調(diào)
? ? ? ? ? ? that.onFulfilledFns.forEach(item=>item(value));
}
};
? ? function reject(reason) {
? ? ? ? //失敗函數(shù)
? ? ? ? if(that.status == 'pending'){
? ? ? ? ? ? that.status = 'rejected';
? ? ? ? ? ? that.value = reason;
? ? ? ? ? ? //執(zhí)行所有失敗的回到
? ? ? ? ? ? that.onRejectedFns.forEach(item=>item(reason));
}
};
? ? //立即執(zhí)行傳入的處理函數(shù)
? ? try{
? ? ? ? task(resolve,reject);
? ? }catch (err){
? ? ? ? reject(err)
}
};
function resolvePromise(promise2,x,resolve,reject) {
? ? let then;
? ? if(promise2 === x){
? ? ? ? return reject(new Error('循環(huán)引用'));
}
? ? if(x instanceof Promise){
? ? ? ? //判斷x的prototype所指向的對(duì)象是否存在Promise的原型鏈上
? ? ? ? if(x.status= 'pending'){
? ? ? ? ? ? x.then(function (y) {
? ? ? ? ? ? ? ? //遞歸 調(diào)用
? ? ? ? ? ? ? ? resolvePromise(promise2,y,resolve,reject);
? ? ? ? ? ? },reject)
? ? ? ? }else if(x.status == 'fulfilled'){
? ? ? ? ? ? resolve(x.value);
? ? ? ? }else if(x.status == 'rejected'){
? ? ? ? ? ? reject(x.value);
}
? ? }else if(x != null && typeof x == 'object' || typeof x == 'function'){
? ? ? ? try{
? ? ? ? ? ? then = x.then;
? ? ? ? ? ? if(typeof then == 'function'){
? ? ? ? ? ? ? ? then.call(x,function (y) {
? ? ? ? ? ? ? ? ? resolvePromise(promise2,y,resolve,reject);
? ? ? ? ? ? ? ? },function (y) {
? ? ? ? ? ? ? ? ? ? reject(y)
});
}
? ? ? ? }catch (e){
? ? ? ? ? ? reject(e);
}
? ? }else{
? ? ? ? resolve(x);
}
}
//then方法
Promise.prototype.then = function (onFulfilled, onRejected) {
? ? //假如沒有傳入異步處理程序則直接返回結(jié)果
? ? onFulfilled = typeof onFulfilled == 'function'?onFulfilled:function (value) {
? ? ? ? return value;
};
? ? onRejected = typeof onRejected == 'function'?onRejected:function (reason) {
? ? ? ? return reason;
};
? ? var promise2;//用來實(shí)現(xiàn)鏈?zhǔn)秸{(diào)用
? ? let that = this;
? ? if(that.status == 'fulfilled'){
? ? ? ? promise2 = new Promise(function (resolve,reject) {
? ? ? ? ? ? let x = onFulfilled(that.value);
? ? ? ? ? ? resolvePromise(promise2,x,resolve,reject);
});
? ? }else if(that.status == 'rejected'){
? ? ? ? promise2 = new Promise(function (resolve,reject) {
? ? ? ? ? ? let x = onRejected(that.value);
? ? ? ? ? ? reject(x);
});
? ? }else if(that.status == 'pending'){
? ? ? ? promise2 = new Promise(function (resolve,reject) {
? ? ? ? ? ? that.onFulfilledFns.push(function(){
? ? ? ? ? ? ? ? let x = onFulfilled(that.value);
? ? ? ? ? ? ? ? resolve(x);
});
? ? ? ? ? ? that.onRejectedFns.push(function () {
? ? ? ? ? ? ? ? let x = onRejected(that.value);
? ? ? ? ? ? ? ? reject(x);
});
});
? ? }else{
? ? ? ? promise2 = new Promise(function (resolve,reject) {
? ? ? ? ? ? reject('Promise內(nèi)部狀態(tài)錯(cuò)誤');
});
}
? ? return promise2;
};
Promise.resolve = function (val) {
? ? return new Promise(function (resolve,reject) {
? ? ? ? resolve(val);
});
};
Promise.reject = function (val) {
? ? return new Promise(function (resolve,reject) {
? ? ? ? reject(val);
});
};
Promise.all = function (arrs) {
? ? //all方法接收一個(gè)promise數(shù)組,數(shù)組中所有異步操作結(jié)束后返回一個(gè)新的promise
? ? if(typeof arrs == 'object' && arrs.length > 0){
? ? ? ? return new Promise(function (resolve,reject) {
? ? ? ? ? ? let result = [];//新的promise返回結(jié)果
? ? ? ? ? ? let indexNum = 0;//當(dāng)前完成幾個(gè)
? ? ? ? ? ? let resolved = function (index) {
? ? ? ? ? ? ? ? return function (data) {
? ? ? ? ? ? ? ? ? ? result[index] = data;
? ? ? ? ? ? ? ? ? ? indexNum++;
? ? ? ? ? ? ? ? ? ? if(indexNum == arrs.length){
? ? ? ? ? ? ? ? ? ? ? ? resolve(result);
}
}
};
? ? ? ? ? ? for(let i=0;i
? ? ? ? ? ? ? ? arrs[i].then(resolved(i),function (reason) {
? ? ? ? ? ? ? ? ? ? reject(reason);
});
};
});
? ? }else{
? ? ? ? return new Promise(function (resolve,reject) {
? ? ? ? ? ? reject(new Error('all方法傳入?yún)?shù)錯(cuò)誤'));
});
}
};
Promise.race = function (arrs) {
? ? if(typeof arrs == 'object' && arrs.length > 0){
? ? ? ? return new Promise(function (resolve,reject) {
? ? ? ? ? ? for(let i=0;i
? ? ? ? ? ? ? ? arrs[i].then(function (data) {
? ? ? ? ? ? ? ? ? ? resolve(data);
? ? ? ? ? ? ? ? },function (err) {
? ? ? ? ? ? ? ? ? ? reject(err);
});
};
});
? ? }else{
? ? ? return new Promise(function (resolve,reject) {
? ? ? ? ? reject(new Error('race方法傳入?yún)?shù)錯(cuò)誤'));
})
};
};