有两种方法,一种是用函数原型链,另一种是用es6提供的class。不过class的本质就是函数原型链。
1. 函数原型链方式
先创建构造函数Promise
function Promise(exe){
this.PromiseState = 'pending'
this.PromiseResult = null
this.callbacks = [] //作用是当《异步调用》时,保存then中的方法。 用数组是因为多个then调用时 用数组储存起来,后续foreach遍历。
let self = this //保存一下this
function resolve(value){
if(self.PromiseState !== 'pending') return //控制Promise只能由pending到fulfilled
self.PromiseResult = value //改变结果
self.PromiseState = 'fulfilled' //改变状态
setTimeout(() => {
self.callbacks.forEach(item => item.onresolved()) //把所有的then方法全部执行
});
}
function reject(reason){
if(self.PromiseState !== 'pending') return //控制Promise只能由pending到reject
self.PromiseResult = reason //改变结果
self.PromiseState = 'rejected' //改变状态
setTimeout(() => {
self.callbacks.forEach(item => item.onrejected()) //把所有的then方法全部执行
});
}
try{
exe(resolve,reject) //立刻同步调用执行
}catch(e){
reject(e)
}
}
创建完构造函数之后,最关键的then方法,它能处理后续内容,并且返回一个promise对象
Promise.prototype.then = function(onresolved,onrejected){
let self = this
return new Promise((resolve,reject)=>{ //.then返回的是Promise对象( let p2 = p.then(fun) )
//用callback函数封装处理then()过程
function callback(type){ //用来处理返回promise对象的状态,如果返回promise对象,则子promise的状态和结果 = 父promise,如果是常量就改变父promise结果
try{
let result = type(self.PromiseResult) //result是then函数体执行后的结果(即return的东西) 他是一个常量或者Promise对象
if(result instanceof Promise){ //如果return的是promise对象,调用result的then来控制父对象 resolve父成功 reject失败
result.then(v =>{resolve(v)},r =>{reject(r)}) //result对象的then可以知道成功还是失败 调用result的then方法只是为了利用成功和失败回调来判断父Promise是成功还是失败
}else{ //如果是常量,直接resolve改变状态
resolve(result)
}
}catch(e){ //当throw的时候直接把promise状态改为失败,并把错误信息交给then promise 对象结果
reject(e)
}
}
if(typeof onresolved !== 'function'){ //如果用户没有在then中传函数类型的参数,则默认返回resolve()中的结果
console.warn('then中第一个参数为回调函数!pjr帮你默认返回结果了')
onresolved = value => value
}
if(typeof onrejected !== 'function'){ //一般都不会写第二个失败的回调,如果有异常直接抛出,一层一层往下找,直到找到有第二个回调的then或者找到catch。
onrejected = reason => {throw reason}
}
if(this.PromiseState == 'fulfilled'){
setTimeout(() => {
callback(onresolved) //同步调用 状态成功 直接在这里处理完毕。
})
}
else if(this.PromiseState == 'rejected'){
setTimeout(() => {
callback(onrejected) //同步调用 状态失败 直接在这里处理完毕。
})
}
else if(this.PromiseState == 'pending'){ //!重点!!! 如果是异步任务,会先进入then,把所有then里的方法保存到实例的callbacks数组里,然后再在resolve或者reject函数里调用callback里的onresolved或者onrejected函数执行
this.callbacks.push({
onresolved:() => callback(onresolved),
onrejected:() => callback(onrejected)
})
}
})
}
then对应有个catch方法,catch方法本质是then的语法糖。并且具有异常穿透
Promise.prototype.catch = function(onrejected){ //catch方法,本质是then的语法糖
this.then(undefined, onrejected)
}
Promise.resolve()方法,快速得到一个成功的Promise对象,如果return 一个新promise对象,新promise对象的结果就是Promise.resolve()的结果
Promise.resolve = function(value){
return new Promise((resolve,reject) =>{
if(value instanceof Promise){
value.then(v => {resolve(v)},r => {reject(r)})
}
else{
resolve(value)
}
})
}
Promise.reject()方法,快速得到一个失败的Promise对象,不管什么情况都是失败的Promise对象
Promise.reject = function(reason){
return new Promise((resolve,reject) =>{
reject(reason)
})
}
Promise.all(promises)方法,传入一个数组(数组名暂定为promises),promises里是几个promise对象。返回结果是一个Promise对象,它的状态由promises每个元素决定,promises里的每个为状态才为真,有一个假状态就是假。返回promise的结果:如果全真,结果是几个promise结果数组;如果有假,结果为假的值。
Promise.all = function(promises){
let arr = [],count = 0;
return new Promise((resolve,reject) => {
for(let i in promises){
promises[i].then(v => {
count++
arr[i] = v
if(count === promises.length){
resolve(arr)
}
},r =>{
reject(r)
})
}
})
}
Promise.race(promises)。类似于Promise.all(),区别是返回结果为第一个完成的promise的结果
Promise.race = function(promises){
return new Promise((resolve,reject) => {
for(let i in promises){
promises[i].then(v => {
resolve(v)
},r => {
reject(r)
})
}
})
}