当前位置:网站首页>高阶函数的应用:手写Promise源码(四)
高阶函数的应用:手写Promise源码(四)
2022-07-23 05:39:00 【Vivqst】
1、优化then方法的抛异常问题
2、根据then方法接收的两个函数参数的返回值类型进行不同的数据处理
// promise/A+规范中说明promise有三种状态,且状态一旦被改变就不能再次发生变化
const PENDING = 'Pending'
const FULFILLED = 'Fulfilled'
const REJECTED = 'Rejected'
class Promise {
// 高阶函数,函数的参数是函数,高阶函数可以实现参数的预置
// 函数的参数中的函数为函数的声明
// executor是立即执行的函数,参数被预置在了constructor中
constructor(executor) {
this.state = PENDING
this.value = undefined // 成功的结果
this.reason = undefined // 失败的理由
// 解决then可以多次调用的问题
this.onResolvedCallbacks = []
this.onRejectedCallbacks = []
const resolve = (value) => {
if(this.state === PENDING) {
this.state = FULFILLED
this.value = value
// 当状态变化时再执行回调函数
this.onResolvedCallbacks.forEach(cb => cb(value))
}
}
const reject = (reason) => {
if(this.state === PENDING) {
this.state = REJECTED
this.reason = reason
// 当状态变化时再执行回调函数
this.onRejectedCallbacks.forEach(cb => cb(reason))
}
}
// 此处为executor函数的调用。参数传入resolve和reject两个函数
try {
executor(resolve, reject)
} catch(err) {
reject(err)
}
}
then(onFulfilledCallback, onRejectedCallback) {
onFulfilledCallback = typeof onFulfilledCallback === 'function' ? onFulfilledCallback : value => value
// 优化抛异常
onRejectedCallback = typeof onRejectedCallback === 'function' ? onRejectedCallback : reason => {
throw reason }
// 可以链式调用,则then返回的必须是一个Promise
let promise = new Promise((resolve, reject) => {
if(this.state === FULFILLED) {
// 优化捕捉异常
setTimeout(() => {
try {
let res = onFulfilledCallback(this.value)
// 根据res的不同类型做不同的处理
resolvePromise(promise, res, resolve, reject)
} catch(e) {
reject(e)
}
})
}
if(this.state === REJECTED) {
setTimeout(() => {
try {
let res = onRejectedCallback(this.reason)
resolvePromise(promise, res, resolve, reject)
} catch(e) {
reject(e)
}
})
}
// 当executor出现异步任务时,then执行的时候,状态还未发生变化,可以将回调放到回调函数数组中
if(this.state === PENDING) {
this.onResolvedCallbacks.push((value) => {
setTimeout(() => {
try {
let res = onFulfilledCallback(value)
resolvePromise(promise, res, resolve, reject)
} catch(e) {
reject(e)
}
})
})
this.onRejectedCallbacks.push((reason) => {
setTimeout(() => {
try {
let res = onRejectedCallback(reason)
resolvePromise(promise, res, resolve, reject)
} catch(e) {
reject(e)
}
})
})
}
})
return promise
}
}
// 根据不同的res类型进行不同的处理
function resolvePromise(promise, res, resolve, reject) {
if(res === promise) {
return reject(new TypeError('死循环'))
}
if(res instanceof Promise) {
try {
res.then(x => {
resolvePromise(promise, x, resolve, reject)
// resolve(x)
})
} catch(e) {
reject(e)
}
} else {
resolve(res)
}
}
let p = new Promise((resolve, reject) => {
console.log(2)
setTimeout(() => {
resolve(1)
}, 0)
})
let p2 = new Promise((resolve, reject) => {
resolve(3)
})
let then = p.then(res => {
console.log(res)
return p2
}).then(res => {
console.log(res)
})
console.log(5)
// 2, 5, 1, 3
边栏推荐
- General view, serializer
- 同步发送短信验证码
- img标签设置height和width无效
- Analysis of flask source code (I) request entry
- 【系统问题】.NET Framework 3.5 安装错误
- Scattered notes of machine learning: some concepts and notes
- Partial usage of C #
- Five methods to prevent over fitting of neural network
- JWT header进行编码过程
- js的事件执行机制(Event loop)
猜你喜欢
随机推荐
图片模糊处理批量生产模糊数据集
[pytho-flask笔记5]蓝图简单使用
通用视图,序列化器
JDBC的学习以及简单封装
Markdown common syntax records
大厂面试机器学习算法(6)时间序列分析
【系统问题】.NET Framework 3.5 安装错误
Error when PLSQL creates Oracle Database: when using database control to configure the database, it is required to configure the listener in the current Oracle home directory. You must run netca to co
js中拼接字符串,注意传参,若为字符串,则需要加转义字符
JWT header for coding process
超链接去掉下划线代码
同步发送短信验证码
[untitled]
Federated primary keys and indexes
MySQL statement queries all child nodes of a level node
RPC与thrift入门
牛客刷题记录--Mysql
Analysis of flask source code (I) request entry
p5面试题
js的继承方式









