通过Promise的功能特性,写一个我们自己的Promise函数,帮助自己更好的去理解Promise异步编程😉
1、源码实现
1.1 ES5的原型方式实现
<!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>Promise</title>
</head>
<body>
<script>
const PENDING = 'pending';
const RESOLVED = 'resolved';
const REJECTED = 'rejected';
function MyPromise(fn) {
/* 保存初始化状态 */
let self = this;
/* 初始化状态 */
this.state = PENDING;
/* 保存 resolve 或者 rejected 传入的值 */
this.value = null
/* 保存 resolve 的回调函数 */
this.resolveCallbacks = [];
/* 保存rejected 的回调函数 */
this.rejectedCallbacks = [];
/* 转态转变为 resolved 的方法 */
function resolve(value) {
// 判断传入元素是否为 Promise 值,如果是, 则状态改变必须等待前一个状态改变后再进行改变
if (value instanceof MyPromise) {
return value.then(resolve, reject);
}
// 保证代码的执行顺序为本轮事件循环的末尾
setTimeout(_ => {
// 只有状态为 pending 时才能转变,
if (self.state === PENDING) {
// 修改状态
self.state = RESOLVED;
// 设置传入的值
self.value = value;
// 执行回调函数
self.resolveCallbacks.forEach(callback => {
callback(value);
})
}
}, 0)
}
/* 状态转变为 rejected 的方法 */
function reject(value) {
// 保证代码的执行顺序为本轮事件循环的末尾
setTimeout(_ => {
// 状态只有为 pending 时才能转变
if (self.state === PENDING) {
// 修改状态
self.state = REJECTED;
// 设置传入的值
self.value = value;
// 执行回调函数
self.rejectedCallbacks.forEach(callback => {
callback(value);
})
}
}, 0)
}
/* 将两个方法传入函数中执行 */
try {
fn(resolve, reject)
} catch (e) {
// 遇到错误的时候,捕获错误,执行 reject 函数
reject(e)
}
}
MyPromise.prototype.then = function (onResolved, onRejected) {
// 首先判断两个参数是否为函数类型,因为这两个参数是可选参数
onResolved = typeof onResolved === 'function' ? onResolved : function (value) {
return value;
};
onRejected = typeof onRejected === 'function' ? onRejected : function (error) {
return error;
};
// 如果是等待状态,则将函数加入对应列表中
if(this.state === PENDING){
this.resolveCallbacks.push(onResolved);
this.rejectedCallbacks.push(onRejected);
}
// 如果状态已经确定,则直接执行对应状态的函数
if(this.state === RESOLVED){
onResolved(this.value)
}
if(this.state === REJECTED){
onRejected(this.value)
}
}
</script>
</body>
</html>
2、使用
let p = new MyPromise(function(resolve, reject){
setTimeout(function(){
return resolve(1)
}, 5000)
})
p.then(res => {
console.log("@res", res);
})
相关文章