一个必须知道的 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 并发模型的内部工作原理奠定坚实的基础。祝您编码愉快!🎉