实现思路:
因为Promise是es6出来的,所以整体设计都使用es5的类和普通function
基本大纲:
(1)当new Promise时,在Promise类内部执行传入的方法体,形参resovle和reject都是类内部定义的方法,用来改变Promise内部的状态和值
(2)当使用.then接收时
会使用.then传入的方法参数,调用该方法,传入执行器中的值,
若执行器同步执行,直接调用
若执行器异步执行,则保存方法到.then前一个Promise上,待到上一个Promise执行器执行时再一起调用
(3)当使用.then返回一个Promise对象时
调用传入.then的方法参数,获取方法的返回值,若返回值是非Promise对象/异常,修改状态和值返回,若返回值是Promise对象,通过.then获取获取到该Promise对象执行结果,然后修改返回的Pomise的状态和值
若获取到的Promise是同步执行,则直接修改返回的Promise的状态和值
若获取到的Promise是异步执行,则会等到执行时,再修改返回的Promise状态和值
接下来是分步骤实现:
Promise类初始结构搭建:
let p = new Promise((resolve, reject) => { //传入的函数是在Promise内部执行的,参数也是在执行时进行传递的
throw new Error('errr'); //遇到抛出异常的情况
resolve('jeff'); //遇到同步执行器调用的情况
setTimeout(() => {
resolve('jeff'); //异步执行器resolve调用情况
reject('errrr'); //异步执行器reject调用情况
},2000)
});
//调用方式
const res=p.then((res)=>{},(err)=>{}).then(...)
const res=p.then((res)=>{}).catch((err)=>{...})
function Promise(executor) {
this.PromiseState = 'pending'; //初始状态为pending
this.PromiseResult = ''; //初始值是空
executor(resovle,reject); //调用传入的方法体,传入resovle/reject形参还未定义
}
resolve、reject执行器和异常捕捉的实现:
//resolve、reject只是改变Promise内部状态和值,.then才会返回结果
//Promise内部的状态只能改变一次,再次改变不会产生影响
function Promise(executor) {
this.PromiseState = 'pending'; //初始状态为pending
this.PromiseResult = ''; //初始值是空
let that = this; //普通function调用时上下文不确定,this指向会出问题
function resolve(val) { //直接使用this会undefined,因为箭头函数和Promise都属于es6,所以这里不使用箭头函数
if (that.PromiseState !== "pending") { //使得状态只能改变一次
return;
}
that.PromiseState = 'fullfilled'; //设置promise对象状态
that.PromiseResult = val; //设置promise对象的值
}
function reject(err) { //失败回调
if (that.PromiseState !== "pending") {
return;
}
that.PromiseResult = err;
that.PromiseState = "rejected";
}
try { //try-catch处理throw抛出异常改变Promise状态
executor(resolve,reject); //执行传入的函数,传递的形参是在Promise内的方法,因为上下文不明确,this会undefined
} catch (err) {
reject(err);
}
}
.then方法接收执行器调用传入的内容实现:
//.then整个方法是同步执行的,.then传入的方法参数,会在执行器执行后执行,故在异步情况,同步执行.then时能先进行方法参数的保存
//resovle/reject执行器只是改变状态和值,.then传入的方法和参数才是接收对应状态下的值
//.then会接收两个方法参数,分别对应resolve/reject执行后调用,方法参数未执行器调用时传入的值
/**
//若执行器是同步调用:根据执行器调用后Promise对象的状态和值,对应调用方法参数并传入值
//若执行器是异步调用:
因为.then这些方法是同步执行的,在执行.then时,Promise对象的状态是pending,状态和值都未改变,而参数方法需要等到状态和值改变时才调用
因此,需要在pending时将方法参数保存下来,选择通过this保存到实例上
因为.then可以分开调用,所以需要将分开调用的各自的方法参数保存起来,选择保存进数组中
在异步任务中等待resolve/reject执行器执行,此时Promise对象状态和值改变
当rosolve/reject执行器执行后,遍历数组,执行对应情况下保存的.then中的方法参数,并传入执行器调用时传入的值
*/
Promise.prototype.then =function(onResolved, onRejected) {//不能使用箭头函数,箭头函数的this会指向外部函数定义时的this,即全局,普通函数的上下文会指向实例
let that = this;
//同步执行下的回调
if (that.PromiseState === 'fullfilled') {
onResolved(that.PromiseResult)
}
//同步执行下的回调
if (that.PromiseState === 'rejected') {
onRejected(that.PromiseResult)
}
if (that.PromiseState === 'pending') {
//当.then方法同步执行,但执行器函数未执行,状态未改变时,保存传递给.then的参数回调,待到改变状态再执行,若使用循环等监听耗费性能
that.callbacks.push({
onResolved,
onRejected
})
}
})
}
function Promise(executor) {
this.PromiseState = 'pending'; //初始状态为pending
this.PromiseResult = ''; //初始值是空
//异步操作下的保存的回调,若有多个.then分开调用,则都会保存下来
this.callbacks =[];
let that = this; //普通function调用时上下文不确定,this指向会出问题
function resolve(val) { //直接使用this会undefined,因为箭头函数和Promise都属于es6,所以这里不使用箭头函数
if (that.PromiseState !== "pending") { //使得状态只能改变一次
return;
}
that.PromiseState = 'fullfilled'; //设置promise对象状态
that.PromiseResult = val; //设置promise对象的值
//执行器异步执行时,同步执行跳过,因为callback并未保存方法
if (that.callbacks.length) { //说明执行器函数异步执行,即调用.then时,状态还未改变,在.then中保存了回调
//当异步执行器改变了状态
that.callbacks.forEach(function (callback) {
callback.onResolved(that.PromiseResult);
})
}
}
function reject(err) { //失败回调
if (that.PromiseState !== "pending") {
return;
}
that.PromiseResult = err;
that.PromiseState = "rejected";
//执行器异步执行时触发,同步执行跳过,因为callbacks并未保存方法
if (that.callbacks.length) { //说明执行器函数异步执行,即调用.then时,状态还未改变,在.then中保存了回调
//当异步执行器改变了状态
that.callbacks.forEach(function(callback){
callback.onRejected(that.PromiseResult);
})
}
}
try { //try-catch处理throw抛出异常改变Promise状态
executor(resolve,reject); //执行传入的函数,传递的形参是在Promise内的方法,因为上下文不明确,this会undefined
} catch (err) {
reject(err);
}
}
.then返回Promise实例对象实现:
//因为当.then中传入的方法参数执行后,能够获取到返回值,且.then返回的Promise1对象的状态和值和返回值相关
//所以,.then返回Promise实例对象的实现,应该在.then中传入的方法参数执行后进行,即在上一个模块的基础上进行
//且在获取到返回值后,需要调用返回的Promise1对象的resolve/reject方法,而这两个方法在Promise外部不好获取
//所以将.then中传入的方法参数执行实现和返回.then返回Promise对象的实现修改为:
/**
Promise.prototype.then =function(onResolved, onRejected) {
return new Promise(function(resolve,reject){
.then中传入的方法参数执行实现和返回.then返回Promise对象的实现
...
})
}
*/
//当方法参数的返回值是正常值/异常时,直接调用要返回的Promise1对象的reject/resolve执行器
//当方法参数的返回值是Promise对象时,需要手动调用该Promise对象.then方法,并传入两个方法参数,在该Promise对象的执行器执行后,就能获取到传递给该Promise对象执行器的值/异常
//在获取到方法参数返回的Promise的值/异常,即在手动调用.then的两个方法参数中,再调用返回的Promise1对象的resolve/reject方法,就能修改其状态和值,同方法参数返回的Promise状态和值相同
//因为.then中方法参数的执行,以及返回内容的获取以及根据返回内容修改.then返回的Promise状态和值是递进执行的,所以抽离成一个方法
Promise.prototype.then =function(onResolved, onRejected) {//不能使用箭头函数,箭头函数的this会指向外部函数定义时的this,即全局,普通函数的上下文会指向实例
let that = this;
return new Promise(function (resolve, reject) { //.then函数必定会返回一个Promise
//封装根据.then返回值进行修改返回的Promise对象的状态和值的方法
function callback(onExcuter) {
try { //捕捉.then方法中抛出的异常
let res=onExcuter(that.PromiseResult); //执行传递给.then的函数参数,并获取返回结果,以便.then链式调用
if (res instanceof Promise) { //如果返回结果是Promise实例,通过.then获取到状态和值则修改返回的Promise状态和结果
res.then((val) => {
resolve(val); //执行后,修改.then返回的Promise对象的值和状态
}, (err) => {
reject(err);
})
} else { //返回普通值
resolve(res);
}
} catch (err) {
reject(err);
}
}
//同步执行下的回调
if (that.PromiseState === 'fullfilled') {
callback(onResolved);
}
//同步执行下的回调
if (that.PromiseState === 'rejected') {
callback(onRejected);
}
if (that.PromiseState === 'pending') {
//当.then方法同步执行,但执行器函数未执行,状态未改变时,保存传递给.then的参数回调给调用.then的Promise上,待到改变状态(调用.then的Promise执行器执行)再执行,若使用循环等监听耗费性能
that.callbacks.push({
onResolved: function () {
callback(onResolved);
},
onRejected: function () {
callback(onRejected);
}
})
}
})
}
链式.then调用实现:
因为上一个模块已经实现了每次.then返回一个Promise对象,所以已经实现了.then链式调用
p.then(方法参数1,方法参数2).then(方法参数11,方法参数22)
调用过程:
当p的执行器resovle/reject/异常执行后,会调用第一个.then对应的方法参数,若p内为异步则会先保存,待到执行器执行后再调用
异步情况且返回Promise对象:
当第一个.then中的方法参数执行后,会根据返回值和异同步状态调用返回Promise的执行器方法,返回的Promise对象会做对应的修改,状态从pending改变
第二个.then因为为同步调用,已经保存了第二个.then中的方法参数到第一个.then返回的Promise对象中,当第一个.then返回的Promise的执行器执行后,修改返回的Promise状态和值,然后才会触发保存到该Promise中的第二个.then中的方法参数,传入执行器执行内容并获取第二个.then方法参数的返回值,然后解析该返回值,修改(即调用第二个.then返回Promise的执行器)第二个.then返回的Promise的状态和值,在修改时若之后还有保存的.then的方法参数,则又会执行其方法参数,并根据返回值修改返回的Promise状态
Promise内每次执行器执行(非then内):修改执行器所属的Promise的值,调用保存的之后的.then的方法参数并传入执行器获取的值,并获取方法参数的返回值,返回值又会通过.then返回的Promise对象的执行器传入调用,从而修改了.then返回的Promise的状态和值,若.then返回的Promise对象中又保存了之后的.then中的方法参数,则会在修改返回的Promise时,又调用之后.then中的方法参数,获取返回值并修改之后.then返回的Promise的状态和值,之后的.then以此类推
.catch、异常穿透、以及不指定.then参数也不中断后续执行实现:
//.catch实现:
//因为.catch和.then的唯一区别是.catch只接收失败回调(reject/throw),返回值等和.then无区别,故完全可以使用.then方法只传入reject对应的回调实现
//异常穿透:
//当未传递.then第二个reject对应的方法参数时,内部手动创建一个会抛出异常的对应回调函数
//则当.then链式调用时,若异步,异常函数会绑定到上一个Promise上,执行reject时,会调用之后.then对应的手动创建的异常函数,会被try-catch一直捕捉,从而一直返回reject形式的Promise,
//直到遇到最后的.catch,.catch对应的回调会在上一个Promise执行reject时调用,从而能接收到链式调用中第一个调用reject/throw传入的值
//.then不传入方法参数也不影响执行
//.then方法实现内部进行判断,若没有传入对应函数,则手动创建一个函数,返回接收到的值,则resolve执行时,调用对应的手动创建的函数,返回值会被放进.then返回的Promise中
Promise.prototype.catch = function (onRejected) {//添加.catch方法,返回结果是和.then相同的返回对象
return this.then(undefined, onRejected);
}
Promise.prototype.then =function(onResolved, onRejected) {//不能使用箭头函数,箭头函数的this会指向外部函数定义时的this,即全局,普通函数的上下文会指向实例
let that = this;
if (typeof onRejected !== 'function') { //实现异常穿透,当未传递.then第二个参数,创建一个函数,当进入callback中会被try-catch捕捉从而修改状态未rejected,值为传入reject的值,若之后的.then没有第二个参数,会一直被捕捉,最终因为.catch中传入了onRejected函数,不为undefined,从而将抛出的值接收,实现异常传统效果,故只要指定一个会修改状态为rejected的函数即可,故该函数还可以修改为返回一个调用了reject(err)的Promise实例对象也可以
//若不指定函数,则会在调用时为undefined的被try-catch捕捉,捕捉的内容也是undefined不是方法,故最终.catch捕获到的内容会是undefined 不是方法,而非reject/throw中的内容,未能实现异常穿透
onRejected = (err) => {
throw err;
}
}
if (typeof onResolved !== 'function') { //实现若第一个参数未传递,会使用该方法,返回的Promise的值依旧为resolve的值和fullfilled状态,不会影响链式.then的执行,否则会因为undefined不是方法中断
onResolved = (val) => val;
}
return new Promise(function (resolve, reject) { //.then函数必定会返回一个Promise
//封装根据.then返回值进行修改返回的Promise对象的状态和值的方法
function callback(onExcuter) {
try { //捕捉.then方法中抛出的异常
let res=onExcuter(that.PromiseResult); //执行传递给.then的函数参数,并获取返回结果,以便.then链式调用
if (res instanceof Promise) { //如果返回结果是Promise实例,通过.then获取到状态和值则修改返回的Promise状态和结果
res.then((val) => {
resolve(val); //执行后,修改.then返回的Promise对象的值和状态
}, (err) => {
reject(err);
})
} else { //返回普通值
resolve(res);
}
} catch (err) {
reject(err);
}
}
//同步执行下的回调
if (that.PromiseState === 'fullfilled') {
callback(onResolved);
}
//同步执行下的回调
if (that.PromiseState === 'rejected') {
callback(onRejected);
}
if (that.PromiseState === 'pending') { //当.then方法同步执行,但执行器函数未执行,状态未改变时,保存传递给.then的参数回调,待到改变状态再执行,若使用循环等监听耗费性能
that.callbacks.push({
onResolved: function () {
callback(onResolved);
},
onRejected: function () {
callback(onRejected);
}
})
}
})
}
修改.then的方法参数调用方式,使其一直为异步调用,进入异步队列中:
//在执行.then中方法参数时,添加setTimeout,使其为异步调用,使得和实际Promise执行效果相同
function Promise(executor) {
//executor内部函数同步调用,resolve/rejected对应的.then等异步调用
this.PromiseState = 'pending';
this.PromiseResult = '';
//异步操作下的保存的回调,若有多个.then分开调用,则都会保存下来
this.callbacks =[];
let that = this;
function resolve(val) { //直接使用this会undefined,因为箭头函数和Promise都属于es6,所以这里不使用箭头函数
if (that.PromiseState !== "pending") { //使得状态只能改变一次
return;
}
that.PromiseState = 'fullfilled'; //设置promise对象状态
that.PromiseResult = val; //设置promise对象的值
//执行器异步执行时,同步执行跳过,因为callback并未保存方法
if (that.callbacks.length) { //说明执行器函数异步执行,即调用.then时,状态还未改变,在.then中保存了回调
//当异步执行器改变了状态
setTimeout(() => {//修改调用方法为异步调用
that.callbacks.forEach(function (callback) {
callback.onResolved(that.PromiseResult);
})
})
}
}
function reject(err) { //失败回调
if (that.PromiseState !== "pending") {
return;
}
that.PromiseResult = err;
that.PromiseState = "rejected";
//执行器异步执行时触发,同步执行跳过,因为callbacks并未保存方法
if (that.callbacks.length) { //说明执行器函数异步执行,即调用.then时,状态还未改变,在.then中保存了回调
//当异步执行器改变了状态
setTimeout(() => { //修改调用方法为异步调用
that.callbacks.forEach(function(callback){
callback.onRejected(that.PromiseResult);
})
})
}
}
try { //try-catch处理throw抛出异常改变Promise状态
executor(resolve,reject); //执行传入的函数,传递的形参是在Promise内的方法,因为上下文不明确,this会undefined
} catch (err) {
reject(err);
}
}
Promise.prototype.then =function(onResolved, onRejected) {//不能使用箭头函数,箭头函数的this会指向外部函数定义时的this,即全局,普通函数的上下文会指向实例
let that = this;
if (typeof onRejected !== 'function') { //实现异常穿透,当未传递.then第二个参数,创建一个函数,当进入callback中会被try-catch捕捉从而修改状态未rejected,值为传入reject的值,若之后的.then没有第二个参数,会一直被捕捉,最终因为.catch中传入了onRejected函数,不为undefined,从而将抛出的值接收,实现异常传统效果,故只要指定一个会修改状态为rejected的函数即可,故该函数还可以修改为返回一个调用了reject(err)的Promise实例对象也可以
//若不指定函数,则会在调用时为undefined的被try-catch捕捉,捕捉的内容也是undefined不是方法,故最终.catch捕获到的内容会是undefined 不是方法,而非reject/throw中的内容,未能实现异常穿透
onRejected = (err) => {
throw err;
}
}
if (typeof onResolved !== 'function') { //实现若第一个参数未传递,会使用该方法,返回的Promise的值依旧为resolve的值和fullfilled状态,不会影响链式.then的执行,否则会因为undefined不是方法中断
onResolved = (val) => val;
}
return new Promise(function (resolve, reject) { //.then函数必定会返回一个Promise
//封装根据.then返回值进行修改返回的Promise对象的状态和值的方法
function callback(onExcuter) {
try { //捕捉.then方法中抛出的异常
let res=onExcuter(that.PromiseResult); //执行传递给.then的函数参数,并获取返回结果,以便.then链式调用
if (res instanceof Promise) { //如果返回结果是Promise实例,通过.then获取到状态和值则修改返回的Promise状态和结果
res.then((val) => {
resolve(val); //执行后,修改.then返回的Promise对象的值和状态
}, (err) => {
reject(err);
})
} else { //返回普通值
resolve(res);
}
} catch (err) {
reject(err);
}
}
//同步执行下的回调
if (that.PromiseState === 'fullfilled') {
setTimeout(() => {//修改调用方法为异步调用
callback(onResolved);
})
}
//同步执行下的回调
if (that.PromiseState === 'rejected') {
setTimeout(() => {//修改调用方法为异步调用
callback(onRejected);
})
}
if (that.PromiseState === 'pending') { //当.then方法同步执行,但执行器函数未执行,状态未改变时,保存传递给.then的参数回调,待到改变状态再执行,若使用循环等监听耗费性能
that.callbacks.push({
onResolved: function () {
callback(onResolved);
},
onRejected: function () {
callback(onRejected);
}
})
}
})
}
Promise最终实现:
function Promise(executor) {
//executor内部函数同步调用,resolve/rejected对应的.then等异步调用
this.PromiseState = 'pending';
this.PromiseResult = '';
//异步操作下的保存的回调,若有多个.then分开调用,则都会保存下来
this.callbacks =[];
let that = this;
function resolve(val) { //直接使用this会undefined,因为箭头函数和Promise都属于es6,所以这里不使用箭头函数
if (that.PromiseState !== "pending") { //使得状态只能改变一次
return;
}
that.PromiseState = 'fullfilled'; //设置promise对象状态
that.PromiseResult = val; //设置promise对象的值
//执行器异步执行时,同步执行跳过,因为callback并未保存方法
if (that.callbacks.length) { //说明执行器函数异步执行,即调用.then时,状态还未改变,在.then中保存了回调
//当异步执行器改变了状态
setTimeout(() => {//修改调用方法为异步调用
that.callbacks.forEach(function (callback) {
callback.onResolved(that.PromiseResult);
})
})
}
}
function reject(err) { //失败回调
if (that.PromiseState !== "pending") {
return;
}
that.PromiseResult = err;
that.PromiseState = "rejected";
//执行器异步执行时触发,同步执行跳过,因为callbacks并未保存方法
if (that.callbacks.length) { //说明执行器函数异步执行,即调用.then时,状态还未改变,在.then中保存了回调
//当异步执行器改变了状态
setTimeout(() => { //修改调用方法为异步调用
that.callbacks.forEach(function(callback){
callback.onRejected(that.PromiseResult);
})
})
}
}
try { //try-catch处理throw抛出异常改变Promise状态
executor(resolve,reject); //执行传入的函数,传递的形参是在Promise内的方法,因为上下文不明确,this会undefined
} catch (err) {
reject(err);
}
}
Promise.prototype.then =function(onResolved, onRejected) {//不能使用箭头函数,箭头函数的this会指向外部函数定义时的this,即全局,普通函数的上下文会指向实例
let that = this;
if (typeof onRejected !== 'function') { //实现异常穿透,当未传递.then第二个参数,创建一个函数,当进入callback中会被try-catch捕捉从而修改状态未rejected,值为传入reject的值,若之后的.then没有第二个参数,会一直被捕捉,最终因为.catch中传入了onRejected函数,不为undefined,从而将抛出的值接收,实现异常传统效果,故只要指定一个会修改状态为rejected的函数即可,故该函数还可以修改为返回一个调用了reject(err)的Promise实例对象也可以
//若不指定函数,则会在调用时为undefined的被try-catch捕捉,捕捉的内容也是undefined不是方法,故最终.catch捕获到的内容会是undefined 不是方法,而非reject/throw中的内容,未能实现异常穿透
onRejected = (err) => {
throw err;
}
}
if (typeof onResolved !== 'function') { //实现若第一个参数未传递,会使用该方法,返回的Promise的值依旧为resolve的值和fullfilled状态,不会影响链式.then的执行,否则会因为undefined不是方法中断
onResolved = (val) => val;
}
return new Promise(function (resolve, reject) { //.then函数必定会返回一个Promise
//封装根据.then返回值进行修改返回的Promise对象的状态和值的方法
function callback(onExcuter) {
try { //捕捉.then方法中抛出的异常
let res=onExcuter(that.PromiseResult); //执行传递给.then的函数参数,并获取返回结果,以便.then链式调用
if (res instanceof Promise) { //如果返回结果是Promise实例,通过.then获取到状态和值则修改返回的Promise状态和结果
res.then((val) => {
resolve(val); //执行后,修改.then返回的Promise对象的值和状态
}, (err) => {
reject(err);
})
} else { //返回普通值
resolve(res);
}
} catch (err) {
reject(err);
}
}
//同步执行下的回调
if (that.PromiseState === 'fullfilled') {
setTimeout(() => {//修改调用方法为异步调用
callback(onResolved);
})
}
//同步执行下的回调
if (that.PromiseState === 'rejected') {
setTimeout(() => {//修改调用方法为异步调用
callback(onRejected);
})
}
if (that.PromiseState === 'pending') { //当.then方法同步执行,但执行器函数未执行,状态未改变时,保存传递给.then的参数回调,待到改变状态再执行,若使用循环等监听耗费性能
that.callbacks.push({
onResolved: function () {
callback(onResolved);
},
onRejected: function () {
callback(onRejected);
}
})
}
})
}
//添加.catch方法,返回结果是和.then相同的返回对象
Promise.prototype.catch = function (onRejected) {
return this.then(undefined, onRejected);
}
class版本es6最终实现:
class Promise{
constructor(executor) {
this.PromiseState = 'pending';
this.PromiseResult = '';
//异步操作下的保存的回调,若有多个.then分开调用,则都会保存下来
this.callbacks =[];
let that = this;
function resolve(val) { //直接使用this会undefined,因为箭头函数和Promise都属于es6,所以这里不使用箭头函数
if (that.PromiseState !== "pending") { //使得状态只能改变一次
return;
}
that.PromiseState = 'fullfilled'; //设置promise对象状态
that.PromiseResult = val; //设置promise对象的值
//执行器异步执行时,同步执行跳过,因为callback并未保存方法
if (that.callbacks.length) { //说明执行器函数异步执行,即调用.then时,状态还未改变,在.then中保存了回调
//当异步执行器改变了状态
setTimeout(() => {//修改调用方法为异步调用
that.callbacks.forEach(function (callback) {
callback.onResolved(that.PromiseResult);
})
})
}
}
function reject(err) { //失败回调
if (that.PromiseState !== "pending") {
return;
}
that.PromiseResult = err;
that.PromiseState = "rejected";
//执行器异步执行时触发,同步执行跳过,因为callbacks并未保存方法
if (that.callbacks.length) { //说明执行器函数异步执行,即调用.then时,状态还未改变,在.then中保存了回调
//当异步执行器改变了状态
setTimeout(() => { //修改调用方法为异步调用
that.callbacks.forEach(function(callback){
callback.onRejected(that.PromiseResult);
})
})
}
}
try { //try-catch处理throw抛出异常改变Promise状态
executor(resolve,reject); //执行传入的函数,传递的形参是在Promise内的方法,因为上下文不明确,this会undefined
} catch (err) {
reject(err);
}
}
then(onResolved, onRejected) {
let that = this;
if (typeof onRejected !== 'function') { //实现异常穿透,当未传递.then第二个参数,创建一个函数,当进入callback中会被try-catch捕捉从而修改状态未rejected,值为传入reject的值,若之后的.then没有第二个参数,会一直被捕捉,最终因为.catch中传入了onRejected函数,不为undefined,从而将抛出的值接收,实现异常传统效果,故只要指定一个会修改状态为rejected的函数即可,故该函数还可以修改为返回一个调用了reject(err)的Promise实例对象也可以
//若不指定函数,则会在调用时为undefined的被try-catch捕捉,捕捉的内容也是undefined不是方法,故最终.catch捕获到的内容会是undefined 不是方法,而非reject/throw中的内容,未能实现异常穿透
onRejected = (err) => {
throw err;
}
}
if (typeof onResolved !== 'function') { //实现若第一个参数未传递,会使用该方法,返回的Promise的值依旧为resolve的值和fullfilled状态,不会影响链式.then的执行,否则会因为undefined不是方法中断
onResolved = (val) => val;
}
return new Promise(function (resolve, reject) { //.then函数必定会返回一个Promise
//封装根据.then返回值进行修改返回的Promise对象的状态和值的方法
function callback(onExcuter) {
try { //捕捉.then方法中抛出的异常
let res=onExcuter(that.PromiseResult); //执行传递给.then的函数参数,并获取返回结果,以便.then链式调用
if (res instanceof Promise) { //如果返回结果是Promise实例,通过.then获取到状态和值则修改返回的Promise状态和结果
res.then((val) => {
resolve(val); //执行后,修改.then返回的Promise对象的值和状态
}, (err) => {
reject(err);
})
} else { //返回普通值
resolve(res);
}
} catch (err) {
reject(err);
}
}
//同步执行下的回调
if (that.PromiseState === 'fullfilled') {
setTimeout(() => {//修改调用方法为异步调用
callback(onResolved);
})
}
//同步执行下的回调
if (that.PromiseState === 'rejected') {
setTimeout(() => {//修改调用方法为异步调用
callback(onRejected);
})
}
if (that.PromiseState === 'pending') { //当.then方法同步执行,但执行器函数未执行,状态未改变时,保存传递给.then的参数回调,待到改变状态再执行,若使用循环等监听耗费性能
that.callbacks.push({
onResolved: function () {
callback(onResolved);
},
onRejected: function () {
callback(onRejected);
}
})
}
})
}
catch(onRejected) {
return this.then(undefined, onRejected);
}
}
类方法实现,不能绑定到原型上,因为实例会继承原型上的属性:
Promise.resolve实现:
//若传入非Promise对象,则直接调用返回的Promise对象的resolve方法,并传入
//若传入Promise对象,则手动添加.then并创建两个方法参数绑定到传入的Promise对象上,当传入的Promise对象执行器执行后,则会调用.then中对应的方法参数,并传入执行器执行值,然后通过要返回的Promise对象的执行器进行调用
Promise.resolve = function (val) {
return new Promise((resolve,reject) => {
if (val instanceof Promise) {
val.then((res) => {
resolve(res);
}, (err) => {
reject(err);
})
} else {
resolve(val)
}
})
}
Promise.reject实现:
//和Promise.resolve原理类似,不过是无论传入何值都会返回rejected状态、值为传入值的Promise对象
Promise.reject = function (val) {
return new Promise((resolve,reject) => {
reject(val);
})
}
Promise.all实现:
//all方法需要等到传入的promise都resolve才会执行返回的Promise对象的resolve方法
//通过计数器实现,每执行了一次.then中的第一个方法参数,就证明成了一次,当次数等于数组长度时满足
//all方法返回的数组内容的顺序和传入的promise的顺序是一致的
//为了避免后方的promise先resolve,不能直接使用数组.push方法保存结果值
//选择使用数组下标保存结果值
//只要有一个返回失败,则最终结果返回失败,故只需要调用reject就行,利用了Promise状态只能改变一次的特点
Promise.all = function (arr) {
return new Promise((resolve, reject) => {
let counts = 0;
let res = [];
for (let i = 0; i < arr.length; i++)
{
arr[i].then((ans) => { //方法未实现传入普通值也能.then获取,实际的Promise是能够传入普通值的
counts++;
res[i] = ans;
if (counts === arr.length) {
resolve(res);
}
}, (err) => {
reject(err);
})
}
})
}
Promise.race实现:
//遍历传入的Promise对象的数组,利用Promise状态只能改变一次的特性,哪个Promise先执行执行器,返回的Promise的状态和值就和最快执行的Promise对象相同
Promise.race=function (promises){
return new Promise((resolve, reject) => {
promises.forEach(promise => { //没有实现传入的是普通值的情况,实际Promise可以传入普通值,且返回的Promise的值也是最前面的普通值
promise.then((res) => {
resolve(res);
}, (err) => {
reject(err);
})
})
})
}