Promise是es6的新特性,在我们的项目开发过程中经常会用到,但是平时用的时候,可能就是知其然而不知其所以然,下面,我们就来实现一个自己promise
const fulfilled = 'fulfilled'
const rejected = 'rejected'
const pending = 'pending'
function resolvePromise(promise2, x, resolve, reject) {
if (promise2 === x) {
throw new Error('类型错误')
}
//判断x是一个普通值还是一个promise
if ((typeof x === 'object' && x !== null) || typeof x === 'function') {
// console.log('x:', x.then());
try {
let then = x.then;
//说明x是一个promise
if (then && typeof then === 'function') {
//执行then方法,this指向X ,成功的回调函数有可能又是一个promise
then.call(x, (y) => {
resolvePromise(promise2, y, resolve, reject)
// resolve(y);
}, (r) => {
reject(r)
})
} else {
resolve(x)
}
} catch (e) {
reject(e)
}
} else {
resolve(x)
}
}
class Promise {
constructor(executor) {
this.status = pending
this.value = '' //存储成功的原因
this.reason = '' //存储失败的原因
this.successFn = [] //保存成功的回调
this.failFn = [] //保存失败的回调
let resolve = (value) => {
if (this.status === pending) {
this.status = fulfilled
//这个value有可能是一个promise
this.value = value
if (this.successFn.length > 0) {
this.successFn.forEach(fn => fn(this.value))
}
}
}
let reject = (reason) => {
if (this.status === pending) {
this.status = rejected
this.reason = reason
if (this.failFn.length > 0) {
this.failFn.forEach(fn => fn(this.reason))
}
}
}
try {
executor(resolve, reject)
} catch (e) {
if (this.status === pending) {
this.status = rejected
this.reason = e
}
}
}
catch(err) {
return this.then(null, err)
}
then(onFulfilled, onRejected) {
// 参数的可选
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : val => val
onRejected = typeof onRejected == 'function' ? onRejected : err => {
throw err
}
let promise2 = new Promise((resolve, reject) => {
if (this.status === pending) {
onFulfilled && this.successFn.push(() => {
try {
let x = onFulfilled(this.value)
resolvePromise(promise2, x, resolve, reject)
} catch (e) {
reject(e)
}
})
onRejected && this.failFn.push(() => {
try {
let x = onRejected(this.reason)
resolvePromise(promise2, x, resolve, reject)
} catch (e) {
reject(e)
}
})
}
if (this.status === fulfilled) {
setTimeout(() => {
try {
let x = onFulfilled(this.value)
resolvePromise(promise2, x, resolve, reject)
} catch (e) {
reject(e)
}
}, 0)
}
if (this.status === rejected) {
setTimeout(() => {
try {
let x = onRejected(this.reason)
resolvePromise(promise2, x, resolve, reject)
} catch (e) {
reject(e)
}
}, 0)
}
})
return promise2
}
resolve(value) {
return new Promise((res, rej) => {
res(value)
})
}
reject(err) {
return new Promise((res, rej) => {
rej(err)
})
}
static resolve(value) {
return new Promise((res, rej) => {
res(value)
})
}
static reject(err) {
return new Promise((res, rej) => {
rej(err)
})
}
//finally方法
finally(callback) {
callback()
return this.then(res => {
return this.resolve(res)
}, err => {
return this.reject(err)
})
}
//race方法
static race(args) {
return new Promise((resolve,reject) =>{
for (let i = 0; i < args.length; i++) {
if (isPromise(args[i])) {
args[i].then(res=>{
resolve(res)
},err =>{
reject(err)
})
} else {
//如果不是promise 直接成功
resolve(args[i])
}
}
})
}
}
//promise的all方法
Promise.all = function(promises){
return new Promise((resolve,reject)=>{
let arr = [];//返回的数组
let i = 0 ;
let processData = (index,data) =>{
arr[index]= data;
if(++i === promises.length ){
resolve(arr)
}
}
for(let i = 0 ; i< promises.length ; i++){
let current = promises[i];
if(isPromise(current)){
current.then(data =>{
processData(i,data)
},reject)
}else {
processData(i,current)
}
}
})
}
function isPromise(fn) {
if ((typeof fn === 'object' && fn !== null) || typeof fn === 'function') {
return fn.then && typeof fn.then === 'function'
}
return false
}
export default Promise
下面是我们的测试文件:
import PromiseMy from './promise'
let p =new PromiseMy((resolve,reject)=>{
resolve('你好啊')
})
// let m = PromiseMy.reject('errrrr')
// m.then((res)=>{
// console.log('res:',res)
// },err =>{
// console.log('err:',err)
// })
// let k = new PromiseMy((resolve,reject) =>{
// resolve('dasdasd')
// })
// k.then(res =>{
// console.log('res1:',res);
// return '50000'
// },err =>{
//
// }).finally(res =>{
// setTimeout(()=>{
// console.log('finally:',res)
//
// },2000)
// }).then(res =>{
// console.log('then2:',res)
// })
//
// PromiseMy.race([12,3,4])
// p .then(res=>{
// console.log('res:',res)
// return new PromiseMy((resolve,reject) =>{
// resolve(new PromiseMy((resolve,reject) =>{
// setTimeout(()=>{
// resolve('jajdasds')
// },1000)
// }))
// })
// }).then(res =>{
// console.log('res2:',res)
// }).catch(err =>{
// console.log('我的catrch方法:',err)
// })
//
// let m = Promise.reject('wocao')
// m.then(res =>{
// console.log('m1:',res)
// },err =>{
// console.log('m:',err)
// })
let p1 = new PromiseMy((resolve,reject) =>{
setTimeout(()=>{
resolve('成功了1')
},2000)
})
let p2 = new PromiseMy((resolve,reject) =>{
setTimeout(()=>{
resolve('成功了2')
},1000)
})
PromiseMy.race([p1,p2]).then(res =>{
console.log('race res :',res)
},err=>{
console.log('race err :,',err)
})
/*
*
* let p = new PromiseMy((resolve, reject) => {
// console.log(xxxx)
reject('你好啊')
})
// .catch(err=>{
// console.log('err:',err)
// }).then(data=>{
// console.log('data:',data)
// })
// let m = PromiseMy.reject('errrrr')
// m.then((res)=>{
// console.log('res:',res)
// },err =>{
// console.log('err:',err)
// })
let k = new PromiseMy((resolve,reject) =>{
resolve('dasdasd')
})
k.then(res =>{
console.log('res1:',res);
return '50000'
},err =>{
}).finally(res =>{
setTimeout(()=>{
console.log('finally:',res)
},2000)
}).then(res =>{
console.log('then2:',res)
})
// PromiseMy.race([12,3,4])
/* p .then(res=>{
console.log('res:',res)
return new PromiseMy((resolve,reject) =>{
resolve(new PromiseMy((resolve,reject) =>{
setTimeout(()=>{
resolve(new PromiseMy((res,rej)=>{
res('ldaskdlsafjsahdkjashdjkash')
}))
},1000)
}))
})
}).then(res =>{
console.log('res2:',res)
}).catch(err =>{
return new PromiseMy((resolve,reject) =>{
resolve(new PromiseMy((resolve,reject) =>{
setTimeout(()=>{
reject(new PromiseMy((res,rej)=>{
res('ldaskdlsafjsahdkjashdjkash')
}))
// resolve('12312312')
},1000)
}))
})
}).then(err =>{
console.log('err:',err)
})*/
//
// let m = Promise.reject('wocao')
// m.then(res =>{
// console.log('m1:',res)
// },err =>{
// console.log('m:',err)
// })
//
// let p1 = new PromiseMy((resolve, reject) => {
// setTimeout(() => {
// resolve('成功了1')
// }, 2000)
// })
//
// let p2 = new PromiseMy((resolve, reject) => {
// setTimeout(() => {
// resolve('成功了2')
// }, 1000)
// })
// //
// PromiseMy.race([p1, p2]).then(res => {
// console.log('race res :', res)
// }, err => {
// console.log('race err :,', err)
// })*/
经过测试可以发现,promise的链式调用以及一些原型上面的方法或者静态方法都已经实现了