一个必须知道的 Js 问题:创建一个基本的自定义 Promise 🌟
简介🌟
JavaScript 的“Promise”是管理异步操作的强大工具,但如果我们想构建自己的 Promise 版本以了解其内部工作原理,该怎么办?在这篇文章中,我们将介绍从头开始创建基本自定义 Promise 的过程,并探索各种修改以增强其功能。在这篇文章的结尾,我们对 Promise、其工作原理以及如何扩展它们有了深刻的理解。
如何构建自定义 Promise
在深入研究代码之前,让我们先分解一下创建 Promise 时需要理解的核心概念。Promise 本质上是一个占位符,用于表示现在或将来可能可用的值,通常是在异步操作完成后。
Promise 的核心组成部分:
循序渐进:建立基本的自定义承诺🏗️
我们首先创建一个自定义 Promise,该 Promise 可以根据异步操作解析或拒绝。以下是我们的实现方法:
这是一个简单的实现:
// Custom Promise constructor
class CustomPromise {
constructor(executor) {
this.state = 'pending'; // Possible states: 'pending', 'fulfilled', 'rejected'
this.value = undefined; // Will hold the result or error
this.successCallbacks = [];
this.errorCallbacks = [];
// Executor is the function passed to the promise
try {
console.log("Executing the promise... 🎯");
executor(this._resolve, this._reject);
} catch (error) {
this._reject(error);
}
}
// Custom resolve function
_resolve = (value) => {
if (this.state === 'pending') {
this.state = 'fulfilled';
this.value = value;
console.log(`Promise resolved with: ${value} ✅`);
this.successCallbacks.forEach(callback => callback(this.value));
}
}
// Custom reject function
_reject = (error) => {
if (this.state === 'pending') {
this.state = 'rejected';
this.value = error;
console.log(`Promise rejected with: ${error} ❌`);
this.errorCallbacks.forEach(callback => callback(this.value));
}
}
// Then method to handle successful promise resolution
then(successCallback) {
if (this.state === 'fulfilled') {
successCallback(this.value);
} else if (this.state === 'pending') {
this.successCallbacks.push(successCallback);
}
return this; // Allows chaining 🔄
}
// Catch method to handle promise rejection
catch(errorCallback) {
if (this.state === 'rejected') {
errorCallback(this.value);
} else if (this.state === 'pending') {
this.errorCallbacks.push(errorCallback);
}
return this; // Allows chaining 🔄
}
}解释📚:
使用自定义承诺🖥️:
现在,让我们使用自定义承诺并记录结果,以便我们可以看到承诺的实际作用:
const myCustomPromise = new CustomPromise((resolve, reject) => {
setTimeout(() => {
const success = true; // Change this to false to test rejection
if (success) {
resolve("Custom promise resolved successfully! 🎉");
} else {
reject("Custom promise was rejected! 😔");
}
}, 2000); // 2-second delay ⏳
});
myCustomPromise
.then((message) => {
console.log("Inside then:", message); // Will print if promise is resolved
})
.catch((error) => {
console.error("Inside catch:", error); // Will print if promise is rejected
});预期输出:
如果“success”变量设置为“true”,则输出将是:
Executing the promise... 🎯 Promise resolved with: Custom promise resolved successfully! 🎉 Inside then: Custom promise resolved successfully! 🎉
如果将“success”变量设置为“false”,则输出将是:
Executing the promise... 🎯 Promise rejected with: Custom promise was rejected! 😔 Inside catch: Custom promise was rejected! 😔
增强和修改🔧
一旦我们有了自定义承诺的基本结构,我们就可以通过多种方式改进它。让我们探索一些有用的修改:
1. 支持多个 then 和 catch 调用的链接🔄
Promise 通常会串联起来以处理连续的异步操作。我们可以增强 `then` 方法以返回新的 Promise,从而允许串联多个处理程序。
then(successCallback) {
const newPromise = new CustomPromise((resolve, reject) => {
const handleSuccess = (value) => {
try {
const result = successCallback(value);
if (result instanceof CustomPromise) {
result.then(resolve).catch(reject);
} else {
resolve(result);
}
} catch (error) {
reject(error);
}
};
if (this.state === 'fulfilled') {
handleSuccess(this.value);
} else if (this.state === 'pending') {
this.successCallbacks.push(handleSuccess);
}
});
return newPromise; // Return the new promise for chaining 🔄
}2. 添加 finally 方法🧹
无论承诺是否被解决或被拒绝,'finally' 方法都会执行回调,通常用于清理任务。
finally(callback) {
return this.then(
(value) => {
callback();
return value; // Pass the resolved value through
},
(error) => {
callback();
throw error; // Pass the rejection through
}
);
}3. 超时功能⏰
有时,我们可能希望对 Promise 强制设置超时。如果 Promise 在给定时间内未解决,则会自动拒绝。
timeout(ms) {
return new CustomPromise((resolve, reject) => {
const timer = setTimeout(() => {
reject('Promise timed out ⏳');
}, ms);
this.then((value) => {
clearTimeout(timer);
resolve(value);
}).catch((error) => {
clearTimeout(timer);
reject(error);
});
});
}4. 静态解析和拒绝方法✅❌
为了创建已经解决或拒绝的承诺,我们可以添加静态方法来模仿 JavaScript 原生的“Promise.resolve()”和“Promise.reject()”的行为。
static resolve(value) {
return new CustomPromise((resolve) => resolve(value));
}
static reject(error) {
return new CustomPromise((_, reject) => reject(error));
}5. 添加 all 和 race 方法⚡
为了同时处理多个承诺,我们可以实现“all”(当所有承诺都实现时解决)和“race”(在第一个承诺解决后立即解决)。
static all(promises) {
return new CustomPromise((resolve, reject) => {
const results = [];
let completed = 0;
promises.forEach((promise, index) => {
promise.then((value) => {
results[index] = value;
completed++;
if (completed === promises.length) {
resolve(results);
}
}).catch(reject);
});
});
}结论
创建自定义 Promise 是了解 JavaScript 如何在后台处理异步操作的绝佳方式。在这篇文章中,我们介绍了 Promise 的基本结构,添加了详细的日志来帮助我们跟踪其进度,并探索了可以实施的几种修改,以使其更加强大。从支持链式和“finally”方法到添加超时功能和处理多个 Promise,这些修改使我们的自定义 Promise 更接近 JavaScript 的原生“Promise”。
随着我们继续尝试异步编程,构建我们自己的类似承诺的实现将为我们理解 JavaScript 并发模型的内部工作原理奠定坚实的基础。祝您编码愉快!🎉