一,整体结构
采用es5的语法来写:
//es5里面自定义模块,用的是IIFE(函数自调用)
(function(window){
//定义promise构造函数
//参数是excutor函数:同步执行
function Promise(excutor){
}
// Promise原型对象的then方法,两个参数是回调函数(成功和失败),返回一个新的promise对象
Promise.prototype.then=function (onResolved,onRejected){
}
// Promise原型对象的catch方法,一个参数是回调函数(失败),返回一个新的promise对象
Promise.prototype.catch=function (onRejected){
}
//Promise函数对象的方法:resolve,返回一个成功值为value的promise对象
Promise.resolve=function(value){
}
//Promise函数对象的方法:reject,返回一个失败值为reason的promise对象
Promise.reject=function(reason){
}
//Promise函数对象的方法:all(接收参数为promise的数组),返回promise对象构成数组(都成功时)
Promise.all=function(promises){
}
//Promise函数对象的方法:race(接收参数为promise的数组),返回promise对象(第一个完成的)
Promise.race=function(promises){
}
//向外暴露这个Promise函数,绑定为window的属性
window.Promise=Promise
})(window)
二,构造函数Promise的实现
第一步:因为excutor是立即同步执行的,所以在promise函数内部需要调用这个excutor函数,并且参数是resolve和reject这两个回调函数。
第二步:因为参数是这两个回调函数,所以这两个回调函数就需要事先定义好。
第三步:根据平时对promise的使用,可以知道,promise必然有个状态属性(peding,resolve,reject),还有一个用于存储结果的属性,还有一个存储回调函数的数组:
//es5里面自定义模块,用的是IIFE(函数自调用)
(function(window){
//定义promise构造函数
//参数是excutor函数:同步执行
function Promise(excutor){
//因为后面resolve和reject是程序员使用者直接在外面调用,this会变成window,故这里保存一下
const that=this
that.status='pending' //给promise对象指定状态属性,初始值为pending
that.data=undefined //给promise对象指定一个用于存储结果数据的属性
that.callbacks=[] //放回调函数的,每个元素的结构:{ onResolved(){},onRejected(){} }
function resolve(value){
//如果状态不是pending,直接结束
if(that.status!=='pending'){
return}
//将状态改为resolved
that.status='resolved'
//保存value数据
that.data=value
//如果有待执行的callback函数,立即异步执行回调函数onResolved
if(that.callbacks.length>0){
setTimeout(()=>{
//让他异步执行,所有成功的回调
that.callbacks.forEach(callbacksObj=>{
callbacksObj.onResolved(value)
})
})
}
}
function reject(reason){
//如果状态不是pending,直接结束
if(that.status!=='pending'){
return}
//将状态改为rejected
that.status='rejected'
//保存reason数据
that.data=reason
//如果有待执行的callback函数,立即异步执行回调函数onRejected
if(that.callbacks.length>0){
setTimeout(()=>{
//让他异步执行,所有成功的回调
that.callbacks.forEach(callbacksObj=>{
callbacksObj.onRejected(reason)
})
})
}
}
//需要立即同步执行excutor函数,但他需要两个回调函数作为参数,故在这之前需要先定义好这两个回调函数
try{
excutor(resolve,reject)
}catch(error){
//如果执行器抛出异常,promise对象变为rejected状态
reject(error)
}
}
// Promise原型对象的then方法,两个参数是回调函数(成功和失败),返回一个新的promise对象
Promise.prototype.then=function (onResolved,onRejected){
//假设当前状态还是pending状态,将回调函数保存起来
this.callbacks.push({
onResolved,
onRejected
})
}
// Promise原型对象的catch方法,一个参数是回调函数(失败),返回一个新的promise对象
Promise.prototype.catch=function (onRejected){
}
//Promise函数对象的方法:resolve,返回一个成功值为value的promise对象
Promise.resolve=function(value){
}
//Promise函数对象的方法:reject,返回一个失败值为reason的promise对象
Promise.reject=function(reason){
}
//Promise函数对象的方法:all(接收参数为promise的数组),返回promise对象构成数组(都成功时)
Promise.all=function(promises){
}
//Promise函数对象的方法:race(接收参数为promise的数组),返回promise对象(第一个完成的)
Promise.race=function(promises){
}
//向外暴露这个Promise函数,绑定为window的属性
window.Promise=Promise
})(window)
也就是说:这部分是excutor实参,
而在promise构造函数内部,第一个执行的就是这个实参函数:
而这里面调用了resolve(1),这个1类比于异步操作的结果
于是就去执行resolve函数,也就是说resolve是定义者定义在promise中,使用者在外面异步操作完成后调用。
而resolve里还要调用.then中的函数:
简单写:
这样就是先指定两个回调函数,等resolve调用时,就可以直接在callbacks里面找到并使用了。
三,then方法的实现
//es5里面自定义模块,用的是IIFE(函数自调用)
(function(window){
const PENDING='pending'
const RESOLVED='resolved'
const REJECTED='rejected'
//定义promise构造函数
//参数是excutor函数:同步执行
function Promise(excutor){
//因为后面resolve和reject是程序员使用者直接在外面调用,this会变成window,故这里保存一下
const that=this
that.status=PENDING //给promise对象指定状态属性,初始值为pending
that.data=undefined //给promise对象指定一个用于存储结果数据的属性
that.callbacks=[] //放回调函数的,每个元素的结构:{ onResolved(){},onRejected(){} }
function resolve(value){
//如果状态不是pending,直接结束
if(that.status!==PENDING){
return}
//将状态改为resolved
that.status=RESOLVED
//保存value数据
that.data=value
//如果有待执行的callback函数,立即异步执行回调函数onResolved
if(that.callbacks.length>0){
setTimeout(()=>{
//让他异步执行,所有成功的回调
that.callbacks.forEach(callbacksObj=>{
callbacksObj.onResolved(value)
})
})
}
}
function reject(reason){
//如果状态不是pending,直接结束
if(that.status!==PENDING){
return}
//将状态改为rejected
that.status=REJECTED
//保存reason数据
that.data=reason
//如果有待执行的callback函数,立即异步执行回调函数onRejected
if(that.callbacks.length>0){
setTimeout(()=>{
//让他异步执行,所有成功的回调
that.callbacks.forEach(callbacksObj=>{
callbacksObj.onRejected(reason)
})
})
}
}
//需要立即同步执行excutor函数,但他需要两个回调函数作为参数,故在这之前需要先定义好这两个回调函数
try{
excutor(resolve,reject)
}catch(error){
//如果执行器抛出异常,promise对象变为rejected状态
reject(error)
}
}
// Promise原型对象的then方法,两个参数是回调函数(成功和失败),返回一个新的promise对象
Promise.prototype.then=function (onResolved,onRejected){
//默认的成功回调函数
onResolved=typeof onResolved === 'function' ? onResolved : value=>value
//指定默认的失败的回调(实现错误/异常传透的关键点)
onRejected=typeof onRejected === 'function' ? onRejected : reason=>{
throw reason}
const that=this
//返回一个新的promise对象,里面的参数依旧是excutor函数
return new Promise((resolve,reject)=>{
//调用指定的回调函数来处理那三种返回值的情况
// 1,如果抛出异常,新promise变为rejected状态,reason为抛出的异常
// 2,如果返回的是非promise的任意值,新promise变为resolved,value为返回的值。
// 3,如果返回的是另一个新的promise,此promise的结果就会变成新promise的结果
function handle(callback){
try{
const result =callback(that.data)
if(result instanceof Promise){
//判断返回是promise的实例对象
result.then(
value=>resolve(value), //当result成功时,让return的promise也成功
reason=>reject(reason) //当result失败时,让return的promise也失败
)
}else{
//返回是非promise的任意值,新promise变为resolved,value为返回的值。
resolve(result)
}
}catch(error){
//这里写得是then的回调函数里面,抛出异常了,新promise变为rejected状态,reason为抛出的异常
reject(error)
}
}
if(that.status===PENDING){
//假设当前状态还是pending状态,此时是先指定回调函数,后改变状态。将回调函数保存起来
//因为需要改状态,所以这样写,而不是直接handle(onResolved)
this.callbacks.push({
onResolved(value){
handle(onResolved)
},
onRejected(reason){
handle(onRejected)
}
})
}else if(that.status===RESOLVED){
//现在已经成功了,必然已经执行了resolve函数,所以结果必然存储在this.status里面
setTimeout(()=>{
handle(onResolved)
})
}else{
//现在已经失败,必然已经执行了reject函数,所以结果必然存储在this.status里面
setTimeout(()=>{
handle(onRejected)
})
}
})
}
// Promise原型对象的catch方法,一个参数是回调函数(失败),返回一个新的promise对象
Promise.prototype.catch=function (onRejected){
return this.then(undefined,onRejected)
}
//Promise函数对象的方法:resolve,返回一个成功值为value的promise对象
Promise.resolve=function(value){
}
//Promise函数对象的方法:reject,返回一个失败值为reason的promise对象
Promise.reject=function(reason){
}
//Promise函数对象的方法:all(接收参数为promise的数组),返回promise对象构成数组(都成功时)
Promise.all=function(promises){
}
//Promise函数对象的方法:race(接收参数为promise的数组),返回promise对象(第一个完成的)
Promise.race=function(promises){
}
//向外暴露这个Promise函数,绑定为window的属性
window.Promise=Promise
})(window)
四,Promise.resolve和reject的实现
//Promise函数对象的方法:resolve,返回一个成功值为value的promise对象
Promise.resolve=function(value){
//返回一个promise成功/失败
return new Promise((resolve,reject)=>{
//value是一个promise时
if(value instanceof Promise){
//根据value的结果作为pormise的结果
value.then(
value=>resolve(value), //当result成功时,让return的promise也成功
reason=>reject(reason) //当result失败时,让return的promise也失败
)
}else{
//value不是一个promise=>promise变为成功,数据是value
resolve(value)
}
})
}
//Promise函数对象的方法:reject,返回一个失败值为reason的promise对象
Promise.reject=function(reason){
//返回一个失败的promise
return new Promise((resolve,reject)=>{
reject(reason)
})
}
五,Promise.all方法
//Promise函数对象的方法:all(接收参数为promise的数组),返回promise对象构成数组(都成功时)
Promise.all=function(promises){
const values =new Array(promises.length)
let acount=0
return new Promise((resolve,reject)=>{
//遍历获取每一个promises内部的promise
promises.forEach((p,index)=>{
p.then(
value=>{
//p成功,将成功的value保存到values里,且要按顺序
values[index]=value
//如果全部成功了,就将return的promise改变为成功
acount++
if(acount===promises.length){
resolve(values)
}
},
reason=>{
//只要一个失败了,return的promise函数就失败
reject(reason)
}
)
})
})
}
六,Promise.race方法
//Promise函数对象的方法:race(接收参数为promise的数组),返回promise对象(第一个完成的)
Promise.race=function(promises){
return new Promise((resolve,reject)=>{
//遍历获取每一个promises内部的promise
promises.forEach((p,index)=>{
p.then(
value=>{
//一旦有成功的,把return变为成功promise
resolve(value)
},
reason=>{
//一旦有失败的,把return变为失败promise
reject(reason)
}
)
})
})
七,整体的promise
//es5里面自定义模块,用的是IIFE(函数自调用)
(function(window){
const PENDING='pending'
const RESOLVED='resolved'
const REJECTED='rejected'
//定义promise构造函数
//参数是excutor函数:同步执行
function Promise(excutor){
//因为后面resolve和reject是程序员使用者直接在外面调用,this会变成window,故这里保存一下
const that=this
that.status=PENDING //给promise对象指定状态属性,初始值为pending
that.data=undefined //给promise对象指定一个用于存储结果数据的属性
that.callbacks=[] //放回调函数的,每个元素的结构:{ onResolved(){},onRejected(){} }
function resolve(value){
//如果状态不是pending,直接结束
if(that.status!==PENDING){
return}
//将状态改为resolved
that.status=RESOLVED
//保存value数据
that.data=value
//如果有待执行的callback函数,立即异步执行回调函数onResolved
if(that.callbacks.length>0){
setTimeout(()=>{
//让他异步执行,所有成功的回调
that.callbacks.forEach(callbacksObj=>{
callbacksObj.onResolved(value)
})
})
}
}
function reject(reason){
//如果状态不是pending,直接结束
if(that.status!==PENDING){
return}
//将状态改为rejected
that.status=REJECTED
//保存reason数据
that.data=reason
//如果有待执行的callback函数,立即异步执行回调函数onRejected
if(that.callbacks.length>0){
setTimeout(()=>{
//让他异步执行,所有成功的回调
that.callbacks.forEach(callbacksObj=>{
callbacksObj.onRejected(reason)
})
})
}
}
//需要立即同步执行excutor函数,但他需要两个回调函数作为参数,故在这之前需要先定义好这两个回调函数
try{
excutor(resolve,reject)
}catch(error){
//如果执行器抛出异常,promise对象变为rejected状态
reject(error)
}
}
// Promise原型对象的then方法,两个参数是回调函数(成功和失败),返回一个新的promise对象
Promise.prototype.then=function (onResolved,onRejected){
//默认的成功回调函数
onResolved=typeof onResolved === 'function' ? onResolved : value=>value
//指定默认的失败的回调(实现错误/异常传透的关键点)
onRejected=typeof onRejected === 'function' ? onRejected : reason=>{
throw reason}
const that=this
//返回一个新的promise对象,里面的参数依旧是excutor函数
return new Promise((resolve,reject)=>{
//调用指定的回调函数来处理那三种返回值的情况
// 1,如果抛出异常,新promise变为rejected状态,reason为抛出的异常
// 2,如果返回的是非promise的任意值,新promise变为resolved,value为返回的值。
// 3,如果返回的是另一个新的promise,此promise的结果就会变成新promise的结果
function handle(callback){
try{
const result =callback(that.data)
if(result instanceof Promise){
//判断返回是promise的实例对象
result.then(
value=>resolve(value), //当result成功时,让return的promise也成功
reason=>reject(reason) //当result失败时,让return的promise也失败
)
}else{
//返回是非promise的任意值,新promise变为resolved,value为返回的值。
resolve(result)
}
}catch(error){
//这里写得是then的回调函数里面,抛出异常了,新promise变为rejected状态,reason为抛出的异常
reject(error)
}
}
if(that.status===PENDING){
//假设当前状态还是pending状态,此时是先指定回调函数,后改变状态。将回调函数保存起来
//因为需要改状态,所以这样写,而不是直接handle(onResolved)
this.callbacks.push({
onResolved(value){
handle(onResolved)
},
onRejected(reason){
handle(onRejected)
}
})
}else if(that.status===RESOLVED){
//现在已经成功了,必然已经执行了resolve函数,所以结果必然存储在this.status里面
setTimeout(()=>{
handle(onResolved)
})
}else{
//现在已经失败,必然已经执行了reject函数,所以结果必然存储在this.status里面
setTimeout(()=>{
handle(onRejected)
})
}
})
}
// Promise原型对象的catch方法,一个参数是回调函数(失败),返回一个新的promise对象
Promise.prototype.catch=function (onRejected){
return this.then(undefined,onRejected)
}
//Promise函数对象的方法:resolve,返回一个成功值为value的promise对象
Promise.resolve=function(value){
//返回一个promise成功/失败
return new Promise((resolve,reject)=>{
//value是一个promise时
if(value instanceof Promise){
//根据value的结果作为pormise的结果
value.then(
value=>resolve(value), //当result成功时,让return的promise也成功
reason=>reject(reason) //当result失败时,让return的promise也失败
)
}else{
//value不是一个promise=>promise变为成功,数据是value
resolve(value)
}
})
}
//Promise函数对象的方法:reject,返回一个失败值为reason的promise对象
Promise.reject=function(reason){
//返回一个失败的promise
return new Promise((resolve,reject)=>{
reject(reason)
})
}
//Promise函数对象的方法:all(接收参数为promise的数组),返回promise对象构成数组(都成功时)
Promise.all=function(promises){
const values =new Array(promises.length)
let acount=0
return new Promise((resolve,reject)=>{
//遍历获取每一个promises内部的promise
promises.forEach((p,index)=>{
p.then(
value=>{
//p成功,将成功的value保存到values里,且要按顺序
values[index]=value
//如果全部成功了,就将return的promise改变为成功
acount++
if(acount===promises.length){
resolve(values)
}
},
reason=>{
//只要一个失败了,return的promise函数就失败
reject(reason)
}
)
})
})
}
//Promise函数对象的方法:race(接收参数为promise的数组),返回promise对象(第一个完成的)
Promise.race=function(promises){
return new Promise((resolve,reject)=>{
//遍历获取每一个promises内部的promise
promises.forEach((p,index)=>{
p.then(
value=>{
//一旦有成功的,把return变为成功promise
resolve(value)
},
reason=>{
//一旦有失败的,把return变为失败promise
reject(reason)
}
)
})
})
}
//向外暴露这个Promise函数,绑定为window的属性
window.Promise=Promise
})(window)