Promise是異步編程的一種解決方案,比回調函數和事件更合理更強大。編程
原生的promise用法以下:數組
let p=new Promise(function(resolve,reject){
resolve('成功');
//reject('失敗');
});
p.then(function(data){
console.log(data);
},function(err){
console.log(err);
});
複製代碼
Promise實例中有一個函數,接受兩個參數,一個是成功的方法,一個是失敗的方法,而後有一個then方法,第一個是成功執行的函數,第二個是失敗執行的函數,而且會接收相應的參數。一旦執行成功,就不會再執行失敗,反之亦然。promise
function Promise(executor){ //executor是一個執行函數
let self = this;
self.status = 'pending';
self.value = undefined; //默認成功的值
self.reason = undefined; //默認失敗的值
function resolve(value){ //成功狀態
if(self.status === 'pending'){
self.status = 'resolved';
self.value = value;
}
}
function reject(reason){ //失敗狀態
if(self.status === 'pending'){
self.status = 'rejected';
self.reason = reason;
}
}
try{
executor(resolve,reject);
}catch(e){ //處理異常狀態,傳給reject
reject(e);
}
};
Promise.prototype.then = function(onFulfilled,onRejected){
let self = this;
if(self.status === 'resolved'){
onFulfilled(self.value);
}
if(self.status === 'rejected'){
onRejected(self.reason);
}
};
module.exports = Promise;
複製代碼
首先先定義一個Promise函數,而且接受一個executor執行函數,將resolve和reject傳參傳進去,定義私有屬性status,value,reason。 Promise有三個狀態,status用來記錄他們: 初始狀態爲pending 成功狀態爲resolved 失敗狀態爲rejectedbash
而後使用prototype掛載一個then方法, 方法中要傳入一個成功的回掉和一個失敗的回掉, 若是成功就調取成功的回掉, 失敗就調取失敗的回掉異步
最後將函數導出,就實現了一個最基礎功能的Promise。異步編程
可是這個Promise仍是一個同步的方法,若是想在代碼中使用異步,好比:函數
let p=new Promise(function(resolve,reject){
setTimeout(function(){
resolve('成功');
},1000);
//throw new Error('錯誤');
});
複製代碼
咱們就須要將他變爲異步的:ui
function Promise(executor){
let self = this;
self.status = 'pending';
self.value = undefined;
self.reason = undefined;
self.onResolvedCallbacks= []; //存放成功的回掉
self.onRejectedCallbacks= []; //存放失敗的回掉
function resolve(value){
if(self.status === 'pending'){
self.status = 'resolved';
self.value = value;
self.onResolvedCallbacks.forEach(function(fn){
fn();
});
}
}
function reject(reason){
if(self.status === 'pending'){
self.status = 'rejected';
self.reason = reason;
self.onRejectedCallbacks.forEach(function(fn){
fn();
});
}
}
try{
executor(resolve,reject);
}catch(e){ //處理異常狀態,傳給reject
reject(e);
}
}
Promise.prototype.then=function(onFulfilled,onRejected){
let self = this;
if(self.status === 'resolved'){
onFulfilled(self.value);
}
if(self.status === 'rejected'){
onRejected(self.reason);
}
if(self.status === 'pending'){
self.onResolvedCallbacks.push(function(){
onFulfilled(self.value);
});
self.onRejectedCallbacks.push(function(){
onRejected(self.reason);
});
}
};
module.exports = Promise;
複製代碼
若是他是異步的,咱們就不能在then方法中用status的成功失敗狀態來判斷他走的那,由於then方法執行後有可能params中還沒執行resolve或者reject,那麼咱們就在Promise實例上再新增onResolvedCallbacks和onRejectedCallbacks兩個數組來存放他的回掉,若是執行的是成功,失敗就會存默認的undefined。在調用時用forEach循環數組依次知性方法。 原生的Promise還能夠then屢次:this
function Promise(executor){
let self = this;
self.status = 'pending';
self.value = undefined;
self.reason = undefined;
self.onResolvedCallbacks= [];
self.onRejectedCallbacks= [];
function resolve(value){
self.status = 'resolved';
self.value = value;
self.onResolvedCallbacks.forEach(function(fn){
fn();
});
}
function reject(reason){
self.status = 'rejected';
self.reason = reason;
self.onRejectedCallbacks.forEach(function(fn){
fn();
});
}
try{
executor(resolve,reject);
}catch(e){
reject(e);
}
};
Promise.prototype.then = function(onFulfilled,onRejected){
let self = this;
let promise2; //實現鏈式操做
if(self.status === 'resolved'){
promise2 = new Promise(function(resolve, reject){
try{
let x = onFulfilled(self.value);
resolve(x);
}catch(e){
reject(e);
}
});
}
if(self.status === 'rejected'){
promise2 = new Promise(function(resolve, reject){
try{
let x = onRejected(self.reason);
reject(x);
}catch(e){
reject(e);
}
});
}
if(self.status === 'pending'){
promise2 = new Promise(function(resolve, reject){
self.onResolvedCallbacks.push(function(){
try{
let x = onFulfilled(self.value);
resolve(x);
}catch(e){
reject(e);
}
});
self.onRejectedCallbacks.push(function(){
try{
let x = onRejected(self.reason);
reject(x);
}catch(e){
reject(e);
}
});
});
}
return promise2;
}
module.exports = Promise;
複製代碼
固然他then的鏈式調用不會有then屬性,因此咱們能夠判斷Promise每次then都會new一個新的Promise咱們用Promise2來表示,then的時候new一個新的Promise而且return給下一個then。 then中不管是成功的回掉仍是失敗的毀掉,只要返回告終果,就會走下一個then中的成功,發生錯誤纔會走下一個then中的失敗,then中能夠return普通值,也可return一個新的Promise,還有可能return 一個{then:xxx},固然更有promise.then().then.then(function(){});這種奇葩的用法spa
function Promise(executor){
let self = this;
self.status = 'pending';
self.value = undefined;
self.reason = undefined;
self.onResolvedCallbacks= [];
self.onRejectedCallbacks= [];
function resolve(value){
self.status = 'resolved';
self.value = value;
self.onResolvedCallbacks.forEach(function(fn){
fn();
});
}
function reject(reason){
self.status = 'rejected';
self.reason = reason;
self.onRejectedCallbacks.forEach(function(fn){
fn();
});
}
try{
executor(resolve,reject);
}catch(e){
reject(e);
}
};
function resolvePromise(p2,x,resolve,reject){
//1.處理亂寫
//2.判斷返回的是否是本身
if(p2 === x){
reject(new typeError('循環引用'));
}
//判斷x是否是params(判斷x是否是object)
let called; //表示是否調用過成功或者失敗
if(x !== null || typeof x === 'object' || typeof x === 'function'){
//判斷promise只要判斷對象中是否有then方法
try{
let then = x.then;
if(typeof then === 'function'){ //then返回的多是{then:xxx},判斷then是否是一個函數
then.call(x,function(y){ //成功了之後可能會執行resolve(new Promise())用遞歸來解決
if(called) return;
called = true;
resolvePromise(p2,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{ //esle普通值
resolve(x);
}
}
Promise.prototype.then = function(onFulfilled,onRejected){ //判斷onFulfilled是否是一個函數,不是給他個函數
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : function(value){
return value;
}
onRejected = typeof onRejected === 'function' ? onRejected : function(err){
throw err;
}
let self = this;
let promise2; //實現鏈式操做
if(self.status === 'resolved'){
promise2 = new Promise(function(resolve, reject){
let x = onFulfilled(self.value);
resolvePromise(promise2,x,resolve,reject);
});
}
if(self.status === 'rejected'){
promise2 = new Promise(function(resolve, reject){
let x = onRejected(self.reason);
resolvePromise(promise2,x,resolve,reject);
});
}
if(self.status === 'pending'){
promise2 = new Promise(function(resolve, reject){
self.onResolvedCallbacks.push(function(){
let x = onFulfilled(self.value);
resolvePromise(promise2,x,resolve,reject);
});
self.onRejectedCallbacks.push(function(){
let x = onRejected(self.reason);
resolvePromise(promise2,x,resolve,reject);
});
});
}
return promise2;
}
module.exports = Promise;
複製代碼
咱們就定義一個resolvePromise來處理then中的返回結果,若是返回的是個錯誤信息,就用try{}catch(){}讓他走reject 最後的最後,Promise中能夠異步執行代碼,then方法中應該也能夠實現異步,很簡單,只要在相應的位置加上setTimeout就ok了,記得不要忘了加上try{}catch(){}來過濾錯誤信息而且傳到reject中
function Promise(executor){
let self = this;
self.status = 'pending';
self.value = undefined;
self.reason = undefined;
self.onResolvedCallbacks= [];
self.onRejectedCallbacks= [];
function resolve(value){
self.status = 'resolved';
self.value = value;
self.onResolvedCallbacks.forEach(function(fn){
fn();
});
}
function reject(reason){
self.status = 'rejected';
self.reason = reason;
self.onRejectedCallbacks.forEach(function(fn){
fn();
});
}
try{
executor(resolve,reject);
}catch(e){
reject(e);
}
};
function resolvePromise(p2,x,resolve,reject){
//1.處理亂寫
//2.判斷返回的是否是本身
if(p2 === x){
reject(new typeError('循環引用'));
}
//判斷x是否是params(判斷x是否是object)
let called; //表示是否調用過成功或者失敗
if(x !== null || typeof x === 'object' || typeof x === 'function'){
//判斷promise只要判斷對象中是否有then方法
try{
let then = x.then;
if(typeof then === 'function'){ //then返回的多是{then:xxx},判斷then是否是一個函數
then.call(x,function(y){ //成功了之後可能會執行resolve(new Promise())用遞歸來解決
if(called) return;
called = true;
resolvePromise(p2,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{ //esle普通值
resolve(x);
}
}
Promise.prototype.then = function(onFulfilled,onRejected){ //判斷onFulfilled是否是一個函數,不是給他個函數
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : function(value){
return value;
}
onRejected = typeof onRejected === 'function' ? onRejected : function(err){
throw err;
}
let self = this;
let promise2; //實現鏈式操做
if(self.status === 'resolved'){
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'){
promise2 = new Promise(function(resolve, reject){
setTimeout(function(){
try{
let x = onRejected(self.reason);
resolvePromise(promise2,x,resolve,reject);
}catch(e){
reject(e);
}
})
});
}
if(self.status === 'pending'){
promise2 = new Promise(function(resolve, reject){
self.onResolvedCallbacks.push(function(){
setTimeout(function(){
try{
let x = onFulfilled(self.value);
resolvePromise(promise2,x,resolve,reject);
}catch(e){
reject(e);
}
})
});
self.onRejectedCallbacks.push(function(){
setTimeout(function(){
try{
let x = onRejected(self.reason);
resolvePromise(promise2,x,resolve,reject);
}catch(e){
reject(e);
}
})
});
});
}
return promise2;
}
module.exports = Promise;
複製代碼