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方法,第一个是成功执行的函数,第二个是失败执行的函数,并且会接收相应的参数。一旦执行成功,就不会再执行失败,反之亦然。
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
失败状态为rejected
然后使用prototype挂载一个then方法,
方法中要传入一个成功的回掉和一个失败的回掉,
如果成功就调取成功的回掉,
失败就调取失败的回掉
最后将函数导出,就实现了一个最基础功能的Promise。
但是这个Promise还是一个同步的方法,如果想在代码中使用异步,比如:
let p=new Promise(function(resolve,reject){
setTimeout(function(){
resolve('成功');
},1000);
//throw new Error('错误');
});
我们就需要将他变为异步的:
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多次:
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(){});这种奇葩的用法
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;