<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<script>
// 添加状态
const PENDING = 'pending';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected';
// 自主实现一个promise
function MyPromise(executor) {
let self = this;
self.state = PENDING; // 刚进入时进行等待状态
self.state = PENDING;
self.value = null;
self.reason = null;
self.onFulfilledCallbacks = []; // 异步调用时,为了保证then方法依然能正常回调,增加回调函数,之所以是数组的形式,是同一个实例对象可以有多个then的方法调用
self.onRejectedCallbacks = []; // 异步调用时,为了保证then方法依然能正常回调,增加回调函数
function resolve(value) {
// 进入该方法时,如果依然是等待的状态,则将状态修改为已完成
if (self.state === PENDING) {
self.state = FULFILLED;
self.value = value;
}
// 执行回调函数
self.onFulfilledCallbacks.forEach(function(fulfilledCallback) {
fulfilledCallback();
});
}
function reject(reason) {
// 进入该方法时,如果依然是等待的状态,则将状态修改为已拒绝
if (self.state === PENDING) {
self.state = REJECTED;
self.reason = reason;
}
// 执行回调函数
self.onRejectedCallbacks.forEach(function(rejectedCallback) {
rejectedCallback();
});
}
try {
executor(resolve, reject);
} catch (reason) {
reject(reason);
}
}
// 实现promise的链式调用,增加一个resolvePromise的方法
MyPromise.prototype.resolvePromise = function(promise2, x, resolve, reject) {
/*
* promise2---then方法当中实例的promise对象,会在then方法中进行返回
* x---是上一个promise当中的返回值
* resolve----promise2实例化方法的成功回调函数
* reject---promise2实例化方法的失败回调函数
* */
let self = this;
let called = false; // called 防止多次调用
if (promise2 === x) {
return reject(new TypeError('循环引用'));
}
if (x !== null && (Object.prototype.toString.call(x) === '[object Object]' || Object.prototype.toString.call(x) === '[object Function]')) {
// x是对象或者函数
try {
let then = x.then;
if (typeof then === 'function') {
// 如果是函数的话,则代表是promise,使用call,将then的方法修改为X这个promise函数,让原本第2个promise中的then执行,去运行它本身
then.call(x, (y) => {
// 别人的Promise的then方法可能设置了getter等,使用called防止多次调用then方法
if (called) return ;
called = true;
// 成功值y有可能还是promise或者是具有then方法等,再次resolvePromise,直到成功值为基本类型或者非thenable
self.resolvePromise(promise2, y, resolve, reject);
}, (reason) => {
if (called) return ;
called = true;
reject(reason);
});
} else {
if (called) return ;
called = true;
resolve(x);
}
} catch (reason) {
if (called) return ;
called = true;
reject(reason);
}
} else {
// x是普通值,直接resolve
resolve(x);
}
};
// 添加.then方法,接收两个函数 onFulfilled 和 onRejected,分别作为Promise成功和失败的回调。所以,在then方法中我们需要对状态state进行判断,如果是fulfilled,则执行onFulfilled(value)方法,如果是rejected,则执行onRejected(reason)方法。
MyPromise.prototype.then = function(onFuifilled, onRejected) {
let self = this;
// promise中可以连续调用,并且会将上一个promise中得到的值,传递到下一个promise的函数中,所有需要实例化多一个promise
let promise2 = null;
promise2 = new MyPromise((resolve, reject) => {
// 注意这里self其实是外层的promise,并且虽然是不同的实例对象,但是有原型继承的关系,所以这个promise2也可以使用then
if (self.state === PENDING) {
self.onFulfilledCallbacks.push(() => {
// promise实际属于微任务,使用setTimeout是实现promise中异步执行
setTimeout(()=>{
try {
// 这里调用的onFuifilled是上个promise中的函数,所以能得到上一个promise的返回值
let x = onFuifilled(self.value);
// 将promise2与上一个promise得到的值作为参数传递,这里注意resolve与reject是promise2实例对象的回调函数
self.resolvePromise(promise2, x, resolve, reject);
} catch(reason) {
reject(reason);
}
},0)
});
self.onRejectedCallbacks.push(() => {
setTimeout(()=>{
try {
let x = onRejected(self.reason);
self.resolvePromise(promise2, x, resolve, reject);
} catch(reason) {
reject(reason);
}
},0)
});
}
if (self.state === FULFILLED) {
setTimeout(()=>{
try {
let x = onFuifilled(self.value);
self.resolvePromise(promise2, x, resolve, reject);
} catch (reason) {
reject(reason);
}
},0)
}
if (self.state === REJECTED) {
setTimeout(()=>{
try {
let x = onRejected(self.reason);
self.resolvePromise(promise2, x, resolve, reject);
} catch (reason) {
reject(reason);
}
},0)
}
});
return promise2;
};
let promise = new MyPromise(function(resolve, reject) {
resolve(123);
})
promise.then(function(value) {
console.log('value', value);
return value + 1;
}, function(reason) {
// console.log('reason', reason);
})
.then(function(v){
console.log(v);
},function(){})
/*输出结果为 123 , 124
*
* */
</script>
</body>
</html>
简单实现一个promise,理解其原理
最新推荐文章于 2023-07-10 14:19:51 发布