标签:cal ack 理解 let cut 完成后 completed catch 思考
Promise通过new Promise 使用,并通常会传入一个函数,这个函数有两个参数,一个是resolve,一个是reject,resolve应该是一个可以解决事情的函数,reject应该是一个当事情没有得到解决时的处理函数,所以Promise应该是一个类,此类的构造器应该传入一个执行器,用来执行处理函数,并且应该有两个处理函数resolve和reject
还可以通过Promise.resolve()和Promise.all()使用,这两方法应该是静态的,所以不通过实例调用,只能是只能类直接调用,所以大概的样子可能是像下面这样:
class MyPromise{
constructor(executor){
executor(this.resolve,this.reject)
}
resolve(){}
reject(){}
static resolve()
static all()
}
从平常使用中可以知道,Promise有如下几个方法供我们使用:
resolve(value),用来处理事情,此方法接收一个参数,可以在Promise实例中直接使用,所有应该考虑其this指向问题
reject(reason),用来处理不能处理事情时的情况,此方法接收一个参数,与resolve相同,可以在Promise实例中直接使用,应该考虑其this指向
then(successCallback,failCallback),这个用来处理当实例中的操作完成后进行的后续操作,可以多次链式调用,此方法接收两个参数,一个是成功的回调,一个是失败的回调,参数都是可选的,每次返回的都是一个Promise实例
finally(callbacl),当Promise的事情处理完后,会进入到此方法,此方法接收一个回调,此方法也是返回一个Promise实例,因此,理论上finally后面还是可以继续链式调用then方法的
catch(callback),当Promise实例执行发生错误时,会进入到此方法,此方法接收一个回调参数来处理错误
Promise.resolve(value),这是一个静态方法,只能直接通过Promise类使用,不能通过实例调用,接收一个参数,返回Promise实例
Promise.all(array),这也是一个静态方法,只能直接通过Promise类使用,不能通过实例调用,接收一个数组参数,返回Promise实例
Promise怎么进行过程控制的?
通过查看Promise原码,发现其使用了几个状态值,pending表示事情未完成成,fulfilled表示事情完成,rejected表示事情失败,那么可以定义这几个常量先:
const PENDING=‘pending‘
const FULFILLED=‘fulfilled‘
const REJECTED=‘rejected‘
首先,状态默认是PENDING状态,当事情处理完成后,状态会变成FULFILLED,当事情失败时,状态会变成REJECTED,那么肯定是有一个变量来储存这个状态了,就叫在Promise中再加一个Status吧
Status=PENDING
后续的resolve和reject就可以改变状态,请继续看
想一下resolve方法都是干嘛的,resolve的作用有几个:
与resolve一样,需要做以下几件事:
then方法接收两个参数,一个successCallback,一个failCallback,参数可选,因为then方法可以链式调用,且方法可能有异步函数,所有采用数组存储的方法来存储回调,then方法返回的是Promise对象
与resolve方法不同,Promise.resolve是把传入的参数转换成Promise对象并返回,所有这个很简单,当传入的参数不是Promise对象时,返回一个新的Promise实例,这个实例resolve了传入的参数,当传入的参数是Promise实例时,直接返回参数
当所有参数数组中的情事都进行完成并成功后,算成功,返回Promise实例,当某一个参数失败时,就算失败,返回Promise实例,这里需要注意的是怎么去判断数组中的情事是否都执行完成,可以用一个数组 result去存储情事结果,遍历参数数组,并用一个数count来记住添加到result中的结果,如果数组项是Promise实例,则通过此项的then方法去向result中添加一个情事,count++,如果不是Promise对象,则直接添加到result中,count++,这样就能保证异步事情都可以在处理完成后把结果存储到result中,当count==参数数组的长度时,就表示参数中的所有异步任务都执行完成并添加到了result中,这时就可以resolve(result)来返回结果了
finally方法其实就是一个then方法,只是它只接收一个回调
通过上面的分析,写出如下代码:
// 定义三个状态常量
const PENDING=‘pending‘
const FULFILLED=‘fulfilled‘
const REJECTED=‘rejected‘
// 创建Promise类
class MyPromiseRepeat{
// 构造函数接收一个执行器
constructor(executor){
//用tryCatch截取错误,并交给reject处理
try {
executor(this.resolve,this.reject)
} catch (error) {
this.reject(error)
}
}
// resolve参数
value=undefined
// 失败原因
reason=undefined
// 状态
Status=PENDING
// 成功回调存储
successCallback=[]
// 失败回调存储
failCallback=[]
// reslove方法
resolve=(value)=>{
// 判断状态
if(this.Status!=PENDING) return
// 更改状态
this.Status=FULFILLED
// 赋值
this.value=value
// 执行成功回调
while(this.successCallback.length) this.successCallback.shift()()
}
reject=(reason)=>{
if(this.Status!=PENDING)return
this.reason=reason
this.Status=REJECTED
while(this.failCallback.length) this.failCallback.shift()()
}
then(successCallback,failCallback){
// 让参数可选,
successCallback=successCallback?successCallback:value=>value
failCallback=failCallback?failCallback:reason=>{throw reason}
// 返回Promise实例
let promise2= new MyPromiseRepeat((resolve,reject)=>{
// 成功时有执行
if(this.Status==FULFILLED){
// 为了能够调用此Promise实例,采用setTimeout来保证拿到promise2
setTimeout(()=>{
// tryCatch截取错误并交给reject
try {
let x=successCallback(this.value)
resolvePromise(promise2,x,resolve,reject)
} catch (error) {
this.reject(error)
}
},0)
// 失败时执行
}else if(this.Status==REJECTED){
setTimeout(()=>{
try {
let x=failCallback(this.reason)
resolvePromise(promise2,x,resolve,reject)
} catch (error) {
this.reject(error)
}
},0)
}else{// 异步操作还没有完成时执行
this.successCallback.push(()=>{
setTimeout(()=>{
try {
let x=successCallback(this.value)
resolvePromise(promise2,x,resolve,reject)
} catch (error) {
this.reject(error)
}
},0)
})
this.failCallback.push(()=>{
setTimeout(()=>{
try {
let x=failCallback(this.reason)
resolvePromise(promise2,x,resolve,reject)
} catch (error) {
this.reject(error)
}
},0)
})
}
})
return promise2
}
finally(callback){
return this.then(value=>{
return MyPromiseRepeat.resolve(callback()).then(()=>value)
},reason=>{
return MyPromiseRepeat.resolve(callback()).then(()=>{throw reason})
})
}
catch(callback){
return this.then(undefined,callback)
}
static resolve(value){
if(value instanceof MyPromiseRepeat) return value
else{
// 不是Promise实例则返回新Promise实例
return new MyPromiseRepeat((resolve)=>{
resolve(value)
})
}
}
static all(array){
let result=[]
let resultCompletedCount=0
return new MyPromiseRepeat((resolve,reject)=>{
function AddResult(index,value){
result[index]=value
resultCompletedCount++
// 当result长度和参数array一样长时,resolve(result)
if(resultCompletedCount==array.length){
resolve(result)
}
}
for(let i =0;i<array.length;i++){
let current= array[i]
if(current instanceof MyPromiseRepeat){
// 为能保证全部执行,异步操作完成后再把结果添加到result
current.then(value=>AddResult(i,value),reason=>reject(reason))
}else{
AddResult(i,array[i])
}
}
})
}
}
function resolvePromise(promise2,x,resolve,reject){
// 这里是识别自调用
if(promise2===x){
return reject(new TypeError(‘Chaining cycle detected for promise #<Promise>‘))
}
// 当异步操作则then
if(x instanceof MyPromiseRepeat){
x.then(resolve,reject)
}else{
resolve(x)
}
}
module.exports=MyPromiseRepeat
标签:cal ack 理解 let cut 完成后 completed catch 思考
原文地址:https://www.cnblogs.com/MissSage/p/14890772.html