Promise/A+规范
Promise相关问题
https://juejin.cn/post/7042679110111330312#heading-9
Terminology
- “promise” is an object or function with a then method whose behavior conforms to this specification.
- “thenable” is an object or function that defines a then method.
- value 是promise状态成功时的值,包括 undefined/thenable或者是 promise
- exception 是一个使用throw抛出的异常值
- reason 是promise状态失败时的值
Requirements
Promise 必须处于以下三个状态之一: pending, fulfilled 或者是 rejected
1.如果promise在pending状态
---可以变成 fulfilled 或者是 rejected
2.如果promise在fulfilled状态
---不会变成其它状态
---必须有一个value值
3.如果promise在rejected状态
---不会变成其它状态
---必须有一个promise被reject的reason
The then Method
promise必须提供一个then方法,来访问最终的结果
promise的then方法接收两个参数
promise.then(onFulfilled, onRejected)
1.onFulfilled 和 onRejected 都是可选参数
onFulfilled 必须是函数类型
onRejected 必须是函数类型
2.如果 onFulfilled 是函数
1.必须在promise变成 fulfilled 时,调用 onFulfilled,参数是promise的value
2.在promise的状态不是 fulfilled 之前,不能调用
3.onFulfilled 只能被调用一次
3.如果 onRejected 是函数:
1.必须在promise变成 rejected 时,调用 onRejected,参数是promise的reason
2.在promise的状态不是 rejected 之前,不能调用
3.onRejected 只能被调用一次
4.onFulfilled 和 onRejected 必须作为函数被调用
5.then方法可能被多次调用
1.如果promise变成了 fulfilled态,所有的onFulfilled回调都需要
按照then的顺序执行
2.如果promise变成了 rejected态,所有的onRejected回调都需要
按照then的顺序执行
7.then必须返回一个promise
promise2 = promise1.then(onFulfilled, onRejected);
1.onFulfilled 或 onRejected 执行的结果为x,调用 resolvePromise
2.如果 onFulfilled 或者 onRejected 执行时抛出异常e,promise2需要被reject
3.如果 onFulfilled 不是一个函数,promise2 以promise1的值fulfilled
4.如果 onRejected 不是一个函数,promise2 以promise1的reason rejected
自定义Promise
//难点分析
// 1.promise中有异步函数,then方法执行时,promiseStatus仍然是pedding状态,如何在promiseStatus改变时调用then的方法
// 2.then返回一个promise对象,当promise中有异步调用时,如何调用
// 3.catch异常穿透问题
enum Status {
Pedding = "Pedding",
Fulfilled = "Fulfilled",
Rejected = "Rejected"
}
interface callBackType{
onResolve:(param:any)=>any
onReject?:(param:any)=>any
}
class CustomPromise {
private promiseStatus: Status = Status.Pedding
private promiseResult: unknown
private callBacks:callBackType[]=[]
constructor(executor) {
const resolve = (data: any) => {
if (this.promiseStatus !== Status.Pedding) {
return
}
this.promiseStatus = Status.Fulfilled
this.promiseResult = data
if (this.callBacks.length!=0) {
setTimeout(()=>{
this.callBacks.forEach(item=>item.onResolve(this.promiseResult))
},0)
}
}
const reject = (error: any) => {
this.promiseStatus = Status.Rejected
this.promiseResult = error
if (this.callBacks.length!=0) {
setTimeout(()=>{
this.callBacks.forEach(item=>{
if (item.onReject) {
item.onReject(this.promiseResult)
}
})
},0)
}
}
try {
executor(resolve, reject)
} catch (error) {
reject(error)
}
}
then(onResolve, onReject?:(params:any)=>any) {
return new CustomPromise((resolve,reject)=>{
// 发现onReject回调函数没有传递就自定义一个。
//并且将前一个then方法执行返回的失败的Promise一直向下抛,
//直到遇见可以处理失败状态的catch函数
if (typeof onReject!='function') {
onReject=function (params) {
throw params
}
}
// onResolve也是一样将结果一直向下传递,直到遇到处理的回调函数
if (typeof onResolve !== 'function') {
onResolve = value => value
}
if (this.promiseStatus === Status.Fulfilled) {
try {
const value= onResolve(this.promiseResult)
resolve(value)
} catch (error) {
reject(error)
}
}
if (this.promiseStatus === Status.Rejected) {
try {
const value= onReject(this.promiseResult)
resolve(value)
} catch (error) {
reject(error)
}
}
if (this.promiseStatus === Status.Pedding) {
this.callBacks.push({onResolve(param){
try {
const value=onResolve(param)
resolve(value)
} catch (error) {
reject(error)
}
},onReject(param){
try {
if (onReject) {
const value=onReject(param)
resolve(value)
}
} catch (error) {
reject(error)
}
}})
}
})
}
catch(onReject:(param:any)=>void){
this.then(undefined,onReject)
}
static all(promises){
return new CustomPromise((resolve, reject) => {
let count = 0
let res:any[]= []
for(let i = 0 ; i < promises.length; i ++){
promises[i].then(value => {
count ++
res[i] = value
if (count === promises.length) {
resolve(res)
}
},reason => {
reject(reason)
})
}
});
}
static race(promises){
return new CustomPromise((resolve, reject) => {
promises.forEach(promise => {
promise.then(value => {
resolve(value)
},reason => {
reject(reason)
})
})
});
}
}
Top comments (0)