自定义 Promise 对象实现:模拟 JavaScript Promise 的行为
自定义 Promise 对象实现:模拟 JavaScript Promise 的行为
本文将深入讲解如何从零开始自定义一个 Promise 对象,模拟 JavaScript 原生 Promise 的行为。从构造函数、状态管理到 then 函数和 resolve/reject 函数的实现,一步步揭示 Promise 的内部运作机制。通过实例代码和测试用例,帮助读者理解 Promise 的原理并掌握自定义 Promise 对象的能力。
1. Promise 构造函数
首先,我们需要创建 Promise 的构造函数,该构造函数接受一个参数,这个参数是个函数,我们一般叫执行函数 (executor function)。执行函数有两个参数,这两个参数也是函数,作用是可以改变 promise 的状态。
function MyPromise(executor) {
this.status = 'pending'; // 初始状态为 pending
this.value = undefined; // resolve 时的返回值
this.reason = undefined; // reject 时的返回值
this.onResolvedCallbacks = []; // 存储成功时的回调函数
this.onRejectedCallbacks = []; // 存储失败时的回调函数
const resolve = (value) => {
if (this.status === 'pending') {
this.status = 'resolve';
this.value = value;
this.onResolvedCallbacks.forEach(fn => fn());
}
};
const reject = (reason) => {
if (this.status === 'pending') {
this.status = 'reject';
this.reason = reason;
this.onRejectedCallbacks.forEach(fn => fn());
}
};
try {
executor(resolve, reject);
} catch (error) {
reject(error);
}
}
2. 设计后续的实验步骤
为了让自定义对象能模拟实现 Promise 的功能,我们需要设计后续的实验步骤,包括:
- **三种状态:**pending-等待, resolve-成功, reject-失败。其中最开始为 pending 状态,并且一旦成功或者失败,Promise 的状态便不会再改变。
- **then 函数:**它有两个参数,'onFulfilled' 表示当状态变为成功时要执行的回调函数,'onRejected' 表示当状态失败时要执行的回调函数。
- 实现 resolve 和 reject 函数。
3. 代码实现
function MyPromise(executor) {
this.status = 'pending'; // 初始状态为 pending
this.value = undefined; // resolve 时的返回值
this.reason = undefined; // reject 时的返回值
this.onResolvedCallbacks = []; // 存储成功时的回调函数
this.onRejectedCallbacks = []; // 存储失败时的回调函数
const resolve = (value) => {
if (this.status === 'pending') {
this.status = 'resolve';
this.value = value;
this.onResolvedCallbacks.forEach(fn => fn());
}
};
const reject = (reason) => {
if (this.status === 'pending') {
this.status = 'reject';
this.reason = reason;
this.onRejectedCallbacks.forEach(fn => fn());
}
};
try {
executor(resolve, reject);
} catch (error) {
reject(error);
}
}
MyPromise.prototype.then = function (onFulfilled, onRejected) {
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : val => val;
onRejected = typeof onRejected === 'function' ? onRejected : err => { throw err };
let promise2 = new MyPromise((resolve, reject) => {
if (this.status === 'resolve') {
setTimeout(() => {
try {
let x = onFulfilled(this.value);
resolvePromise(promise2, x, resolve, reject);
} catch (error) {
reject(error);
}
}, 0);
}
if (this.status === 'reject') {
setTimeout(() => {
try {
let x = onRejected(this.reason);
resolvePromise(promise2, x, resolve, reject);
} catch (error) {
reject(error);
}
}, 0);
}
if (this.status === 'pending') {
this.onResolvedCallbacks.push(() => {
setTimeout(() => {
try {
let x = onFulfilled(this.value);
resolvePromise(promise2, x, resolve, reject);
} catch (error) {
reject(error);
}
}, 0);
});
this.onRejectedCallbacks.push(() => {
setTimeout(() => {
try {
let x = onRejected(this.reason);
resolvePromise(promise2, x, resolve, reject);
} catch (error) {
reject(error);
}
}, 0);
});
}
});
return promise2;
};
function resolvePromise(promise2, x, resolve, reject) {
if (promise2 === x) {
return reject(new TypeError('Chaining cycle detected for promise'));
}
let called = false;
if (x !== null && (typeof x === 'object' || typeof x === 'function')) {
try {
let then = x.then;
if (typeof then === 'function') {
then.call(x, y => {
if (called) return;
called = true;
resolvePromise(promise2, y, resolve, reject);
}, err => {
if (called) return;
called = true;
reject(err);
})
} else {
resolve(x);
}
} catch (error) {
if (called) return;
called = true;
reject(error);
}
} else {
resolve(x);
}
}
MyPromise.resolve = function (value) {
return new MyPromise((resolve, reject) => {
resolve(value);
});
};
MyPromise.reject = function (reason) {
return new MyPromise((resolve, reject) => {
reject(reason);
});
};
4. 测试代码
let promise = new MyPromise((resolve, reject) => {
setTimeout(() => {
resolve('success');
}, 1000);
});
promise.then((value) => {
console.log(value); // 输出 'success'
}, (reason) => {
console.log(reason);
});
通过这段测试代码,我们可以看到自定义的 Promise 对象能够成功模拟 JavaScript 原生 Promise 的行为,并且可以正确地执行 then 函数中的回调函数。
总结
本文通过自定义一个 Promise 对象,深入浅出地讲解了 Promise 的内部机制,并提供了相应的代码实现和测试用例。相信读者通过学习本文能够对 Promise 有更深入的理解,并能够在实际项目中灵活运用 Promise 进行异步编程。
原文地址: https://www.cveoy.top/t/topic/nwys 著作权归作者所有。请勿转载和采集!