Fetch the repository succeeded.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<script>
// 将普通任务转换成异步 微任务
function createAsyncTask(task) {
if (typeof queueMicrotask === 'function') {
queueMicrotask(() => {
task()
})
} else {
setTimeout(() => {
task()
}, 0)
}
}
//抽取复用代码
function handleePromise(p2, x, resolve, reject) {
// 判断是不是循环引用(重复引用)
if (x === p2) {
throw new TypeError('Chaining cycle detected for promise #<Promise>')
}
// 判断x是不是promise实例对象
if (x instanceof MyPromise) {
x.then(
(res) => {
resolve(res)
},
(err) => {
reject(err)
}
)
} else {
resolve(x)
}
}
const PENDING = 'pending'
const REJECTED = 'rejected'
const FULFILLED = 'fulfilled'
// 类
class MyPromise {
#handles = [] // 私有属性 用来保存回调函数
// 构造函数
constructor(func) {
this.state = PENDING // 初始状态
this.result = undefined // 初始结果
const resolve = (result) => {
if (this.state === PENDING) {
this.state = FULFILLED
this.result = result
this.#handles.forEach((v) => {
v.onFulfilled()
})
}
}
const reject = (result) => {
if (this.state === PENDING) {
this.state = REJECTED
this.result = result
this.#handles.forEach((v) => {
v.onRejected()
})
}
}
try {
func(resolve, reject)
} catch (error) {
reject(error)
}
}
// 实例方法
then(onFulfilled, onRejected) {
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : (x) => x
onRejected =
typeof onRejected === 'function'
? onRejected
: (x) => {
throw x
}
// then方法需要返回一个新的 Promise实例
const p2 = new MyPromise((resolve, reject) => {
if (this.state === FULFILLED) {
createAsyncTask(() => {
try {
// x是then的第一个形参函数的返回值
let x = onFulfilled(this.result)
handleePromise(p2, x, resolve, reject)
} catch (error) {
reject(error)
}
})
} else if (this.state === REJECTED) {
createAsyncTask(() => {
try {
// x是then的第一个形参函数的返回值
let x = onRejected(this.result)
handleePromise(p2, x, resolve, reject)
} catch (error) {
reject(error)
}
})
} else if (this.state === PENDING) {
// 解决异步 ,保存成功/失败回调函数
this.#handles.push({
onFulfilled: () => {
createAsyncTask(() => {
try {
// x是then的第一个形参函数的返回值
let x = onFulfilled(this.result)
handleePromise(p2, x, resolve, reject)
} catch (error) {
reject(error)
}
})
},
onRejected: () => {
createAsyncTask(() => {
try {
// x是then的第一个形参函数的返回值
let x = onRejected(this.result)
handleePromise(p2, x, resolve, reject)
} catch (error) {
reject(error)
}
})
}
})
}
})
return p2
}
catch(onRejected) {
// 内部调用then函数
return this.then(undefined, onRejected)
}
finally(onFinally) {
this.then(onFinally, onFinally)
}
// 静态方法
static resolve(value) {
if (value instanceof MyPromise) {
return value
}
return new Mypromise((resolve, reject) => {
resolve(value)
})
}
static reject(value) {
if (value instanceof MyPromise) {
return value
}
return new Mypromise((resolve, reject) => {
reject(value)
})
}
static race(promises) {
return new MyPromise((resolve, reject) => {
if (!Array.isArray(promises)) {
return reject(new TypeError('argument is not iterable'))
}
promises.forEach((p) => {
MyPromise.resolve(p).then(
(res) => {
resolve(res)
},
(err) => {
reject(err)
}
)
})
})
}
static all(promises) {
return new MyPromise((resolve, reject) => {
// 判断参数是不是数组
if (!Array.isArray(promises)) {
return reject(new TypeError('argument is not iterable'))
}
// 空数组 直接兑现
promises.length == 0 && resolve(promises)
let resolves = []
let count = 0
promises.forEach((p, index) => {
MyPromise.resolve(p).then(
(res) => {
// 保证结果跟 Promise 数组参数顺序一致
resolves[index] = res
count++
count === promises.length && resolve(resolves) // 全部兑现之后,再兑现结果
},
(err) => {
reject(err)
}
)
})
})
}
}
// ---------------------------测试代码----------------------------------
const p1 = new MyPromise((resolve, reject) => {
resolve('1成功')
// reject('1错误')
// throw new Error('error')
// setTimeout(() => {
// resolve('1成功')
// }, 2000)
})
const p2 = p1
.then((res) => {
console.log('成功then1:', res)
// throw new Error('error')
return new MyPromise((resolve, reject) => {
setTimeout(() => {
reject(222)
}, 2000)
})
})
.catch((err) => {
console.log(err)
})
.finally(() => {
console.log('finally')
})
</script>
</body>
</html>
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。