code2021-l
Version:
前端自定义工具
278 lines (247 loc) • 7.66 kB
HTML
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>手写Promise</title>
</head>
<body>
<script>
const PENDING = 'pending' // 初始/未确定
const RESOLVED = 'resolved' // 成功
const REJECTED = 'rejected' // 失败
function Promise(excutor) {
const self = this
self.status = PENDING
self.data = undefined
/*
{
onResolved: function (){},
onRejected: function (){}
}
*/
self.callbacks = [] // 用来保存所有待处理的成功和失败的回调函数
function resolve(value) {
// 如果当前promise不是pending, 直接结束
if (self.status!==PENDING) return
// 立即改状态
self.status = RESOLVED
// 立即存数据
self.data = value
// 异步调用待处理的成功的回调函数
setTimeout(() => {
self.callbacks.forEach(callbackObj => {
callbackObj.onResolved(value)
})
})
}
function reject(reason) {
// 如果当前promise不是pending, 直接结束
if (self.status!==PENDING) return
// 立即改状态
self.status = REJECTED
// 立即存数据
self.data = reason
// 异步调用待处理的成功的回调函数
setTimeout(() => {
self.callbacks.forEach(callbackObj => {
callbackObj.onRejected(reason)
})
})
}
try {
// 立即执行执行器函数
excutor(resolve, reject)
} catch (error) {
reject(error)
}
}
/*
1. 返回一个新的promise
2. 新的promise的状态由onResolved/onRejected执行的结果决定
1). 返回一个非promise ===> 成功
2). 抛出异常 ===> 失败
3). 返回一个promise ===> 与这个promise的结果一致
3. 在then中要对onResolved/onRejected进行处理: 根据当前promise的状态来操作
1). resolved: 异步调用onResolved
2). rejected: 异步调用onRejected
3). pending: 将onResolved/onRejected保存到callbacks中
*/
Promise.prototype.then = function (onResolved, onRejected) {
const self = this
// 如果onResolved不是函数, 需要针value传递下去
onResolved = typeof onResolved === 'function' ? onResolved : value => value
// 如果onRejected不是函数, 需要针reason传递下去
onRejected = typeof onRejected === 'function' ? onRejected : reason => {throw reason}
// 返回一个新的promise
return new Promise((resolve, reject) => {
/*
调用指定的回调函数
根据执行的结果, 更新返回promise的状态
*/
function handleCallback(callback) {
try {
const result = callback(self.data)
if (result instanceof Promise) {
result.then(
value => {resolve(value)},
reason => {reject(reason)}
)
// result.then(resolve, reject)
} else {
resolve(result)
}
} catch (error) {
reject(error)
}
}
if (self.status===RESOLVED) {
setTimeout(() => {
handleCallback(onResolved)
})
} else if (self.status===REJECTED) {
setTimeout(() => {
handleCallback(onRejected)
})
} else { // PENDING
// 保存回调函数
self.callbacks.push({
onResolved: value => handleCallback(onResolved),
onRejected: reason => handleCallback(onRejected)
})
}
})
}
Promise.prototype.catch = function (onRejected) {
return this.then(undefined, onRejected)
}
Promise.resolve = function (value) { // value有可能是一个promise
return new Promise((resolve, reject) => {
if (value instanceof Promise) {
value.then(resolve, reject)
} else {
resolve(value)
}
})
}
Promise.reject = function (reason) {
return new Promise((resolve, reject) => {
reject(reason)
})
}
Promise.resolveDelay = function (value, time) {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (value instanceof Promise) {
value.then(resolve, reject)
} else {
resolve(value)
}
}, time)
})
}
Promise.rejectDelay = function (reason, time) {
return new Promise((resolve, reject) => {
setTimeout(() => {
reject(reason)
}, time)
})
}
Promise.race = function (promises) {
return new Promise((resolve, reject) => {
promises.forEach(p => p.then(resolve, reject))
})
}
Promise.all = function (promises) {
return new Promise((resolve, reject) => {
const values = []
let resolvedCount = 0
promises.forEach((p, index) => {
p.then(
value => {
resolvedCount++
values[index] = value
if (resolvedCount===promises.length) {
resolve(values)
}
},
reason => reject(reason)
)
})
})
}
</script>
<script>
const p1 = Promise.resolve(5)
const p2 = Promise.resolve(Promise.reject(6))
const p3 = Promise.resolveDelay(7, 1000)
const p4 = Promise.rejectDelay(8, 2000)
// p1.then(value => console.log('p1', value))
// p2.catch(reason => console.log('p2', reason))
// p3.then(value => console.log('p3', value))
// p4.catch(reason => console.log('p4', reason))
// const p5 = Promise.race([p3, p1])
// const p5 = Promise.race([p3, p2])
// p5.then(
// value => console.log('race onResolved()', value),
// reason => console.log('race onRejected()', reason),
// )
// const p6 = Promise.all([p1, p3])
const p6 = Promise.all([p2, p3])
p6.then(
vales => console.log('all onResolved()', vales),
reason => console.log('all onRejected()', reason),
)
</script>
<!--
<script>
new Promise((resolve, reject) => { // excutor
// 遍历异步任务
setTimeout(() => {
// 如果成功
// resolve(1)
// 如果失败
reject(2)
}, 1000)
// throw 3
})
.then(
value => {
console.log('onResolved1()', value)
}, // onResolved
reason => {
console.log('onRejected1()', reason)
throw 3
} // onRejected
)
.then(
value => {
console.log('onResolved2()', value)
}, // onResolved
reason => {
console.log('onRejected2()', reason)
} // onRejected
)
.then(
value => {
console.log('onResolved3()', value)
}
)
.catch(
reason => {
console.log('catch()', reason)
}
)
.then(
value => {
console.log('onResolved4()', value)
},
reason => {
console.log('onRejected4()', reason)
}
)
console.log('new Promise()之后')
</script> -->
</body>
</html>