HTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<!-- 引入我们自己封装的Promise文件,文件定义里面 Promise,这时系统自带的Promise失效-->
<script src="./myPromise.js"></script>
</head>
<body></body>
<script>
const p = new Promise((resolve, reject) => {
// 同步函数resolve
// resolve('ok1')
// 同步函数reject
// reject('err')
// 异步函数测试
// setTimeout(() => {
// 异步函数resolve
// resolve('ok')
// 异步函数reject
// resolve('error')
// }, 1000)
})
// 链式调用
const res = p.then(
// resolve回调
value => {
// resolve('ok') 则value输出ok
// console.log(value)
// 返回另外一个Promise对象
// return new Promise((resolve, reject) => {
// promise执行异步函数
// setTimeout(() => {
// resolve('promise ok')
// console.log(value)
// }, 1000)
// })
// 执行resolve()错误抛出
// throw "FAIL1"
},
// reject回调
reason => {
// reject('err') 则reason输出err
// console.log(reason)
// 执行reject()错误抛出
// throw "FAIL2"
}
)
// 输出res 查看Premise状态
console.log(res)
</script>
</html>
JavaScript
// 封装Promise
// 声明构造函数
// 注:这里声明的函数会直接把系统的Promise函数覆盖
function Promise(executor) {
// 状态开始为pending
this.PromiseState = 'pending'
// 返回值开始为null
this.PromiseResult = null
// 声明属性,保存回调函数
this.callback = []
// 锁定this,这里this指向Promise对象
// 参考:如果是在new中调用,this则为新创建的对象
// 若resolve/reject为箭头函数,此处可省略
const _this = this
// resolve函数
function resolve(data) {
// 状态改变,则不可逆
if (_this.PromiseState !== 'pending') return
// 改变pending状态为resolved
_this.PromiseState = 'resolved'
// 传入data
_this.PromiseResult = data
// 这里对应then函数 如果Promise传入的是一个异步代码
// 那么PromiseState就是一个pending状态
// 所以要再次执行调用Promise,直到PromiseState为resolved或者resolved为止
// 这里传入data用于下一次执行Promise的传参
_this.callback.forEach(item => {
item.onResolved(data)
})
}
// reject函数
function reject(data) {
// 状态改变,则不可逆
if (_this.PromiseState !== 'pending') return
// 改变pending状态为rejected
_this.PromiseState = 'rejected'
// 传入data
_this.PromiseResult = data
_this.callback.forEach(item => {
item.onRejected(data)
})
}
// 抛出异常处理
try {
// 同步调用execltor
execltor(resolve, reject)
} catch (error) {
// 修改promise对象状态为失败
reject(error)
}
}
// 核心:then函数 传入成功会执行的代码和失败会执行的代码
Promise.prototype.then = function (onResolved, onRejected) {
// 返回Promise对象 用于链式调用
return new Promise((resolve, reject) => {
// 封装函数 用于状态为resolved时或rejected时执行
// type 当状态为resolved则为onResolved(this.PromiseResult)
// 当状态为rejected则为onRejected(this.PromiseResult)
// handle函数作用:判断是否是Promise对象,如果不是,改变状态,传出结果
// 如果是,继续调用then 另捕捉throw传出的错误且改变状态
const handle = type => {
// 错误处理 用于捕捉throw 'FAIL'
try {
// 执行成功/失败会执行的函数
let result = type(this.PromiseResult)
// 若返回值为Promise对象,则继续递归执行then
if (result instanceof Promise) {
// 链式调用then,传入成功和失败代码片段
result.then(
v => {
resolve(v)
},
r => {
reject(r)
}
)
} else {
// 如果不是Promise对象,改变状态,传出result
resolve(result)
}
} catch (error) {
// 如果是throw,直接失败,传出抛出的error
reject(error)
}
}
// 调用回调函数
// 如果状态为resolved
if (this.PromiseState === 'resolved') {
// 使用handle改变状态 确定结果
handle(onResolved)
}
// 如果状态为rejected
if (this.PromiseState === 'rejected') {
// 使用handle改变状态 确定结果
handle(onRejected)
}
// 如果状态为pending
// 代表着Promise里面传入的为异步函数
if (this.PromiseState === 'pending') {
// 将需要执行的异步函数存入callback数组
// 当异步函数结束,调用resolve / reject时,对应上面this.callback.forEach执行
this.callback.push({
onResolved: () => {
handle(onResolved)
},
onRejected: () => {
handle(onRejected)
},
})
}
})
}