深入理解JavaScript:手写Promise实现原理
需积分: 5 200 浏览量
更新于2024-11-16
收藏 1KB ZIP 举报
知识点一:Promise基本概念
Promise是JavaScript中处理异步操作的一个核心概念,它代表了一个可能尚未完成,但预期在未来某个时间点能够完成的异步操作的结果。Promise有三种状态:pending(等待中)、fulfilled(已成功)和rejected(已失败)。状态一旦改变,就不会再变。
知识点二:Promise的方法
Promise的主要方法包括then()、catch()、finally()。then()方法可以接受两个参数,分别是状态变为fulfilled时和rejected时要执行的函数。catch()方法则是then(null, rejectionHandler)的语法糖,专门用来处理拒绝的情况。finally()方法无论Promise被解决或被拒绝都会执行。
知识点三:Promise的构造函数
Promise是通过构造函数创建的,构造函数接收一个执行器函数(executor)作为参数。执行器函数又接受两个参数,通常命名为resolve和reject,这两个参数也是函数。当异步操作执行成功时,调用resolve(value),Promise的状态变为fulfilled;当异步操作失败时,调用reject(reason),Promise的状态变为rejected。
知识点四:手写Promise的步骤
要实现一个简化版的Promise,需要理解几个关键点:
1. 实现一个构造函数,可以接收一个执行器函数。
2. 构造函数内部需要有状态保存的变量,以及成功和失败的回调函数列表。
3. 实现resolve和reject函数,用于改变Promise的状态,并将相应回调函数加入到队列中。
4. then()方法需要实现两个回调函数的注册,并且处理链式调用的情况。
5. 需要处理异步逻辑,即确保then()注册的回调函数在下一个事件循环中执行。
知识点五:Promise的链式调用
Promise的链式调用是通过then()方法实现的。当then()中返回一个新的Promise对象时,下一个then()的调用会等待这个新的Promise对象被解决或被拒绝。如果then()方法中返回的是一个非Promise值,则这个值会被包装在一个解决状态的Promise中。
知识点六:Promise的异常处理
Promise的异常处理主要通过catch()方法和then()方法的第二个参数来实现。在Promise链的任何位置抛出的错误,都可以被就近的catch()捕获。如果没有就近的catch()捕获,则错误会被传递到下一个then()的第二个参数中。如果整个Promise链没有捕获到错误,则在全局范围内会被捕获。
知识点七:Promise的其他特性
- Promise.all()方法用于处理多个Promise对象的并行执行,只有所有的Promise都成功解决时才解决,否则任何一个Promise被拒绝就立即拒绝。
- Promise.race()方法用于处理多个Promise对象的竞态执行,第一个完成的Promise的状态会被采纳。
- Promise.resolve()和Promise.reject()是用于创建已经解决或已拒绝的Promise的静态方法。
知识点八:手写Promise的代码实现
以下是一个简化版Promise的手写示例代码(main.js中的内容):
```javascript
// Promise构造函数
function MyPromise(executor) {
// 初始状态
var self = this;
self.state = 'pending';
self.value = null;
self.reason = null;
// 成功的回调队列
self.onFulfilledCallbacks = [];
// 失败的回调队列
self.onRejectedCallbacks = [];
// resolve函数
function resolve(data) {
// 成功状态只能改变一次
if(self.state === 'pending') {
self.state = 'fulfilled';
self.value = data;
// 执行成功的回调
self.onFulfilledCallbacks.forEach(fn => fn(data));
}
}
// reject函数
function reject(data) {
// 失败状态只能改变一次
if(self.state === 'pending') {
self.state = 'rejected';
self.reason = data;
// 执行失败的回调
self.onRejectedCallbacks.forEach(fn => fn(data));
}
}
try {
// 立即执行executor,并传入resolve和reject函数
executor(resolve, reject);
} catch (error) {
// 如果执行出错,直接执行reject
reject(error);
}
}
// MyPromise.prototype.then()方法
MyPromise.prototype.then = function(onFulfilled, onRejected) {
// 调用时传入的参数不一定是函数,需要进行判断
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : data => data;
onRejected = typeof onRejected === 'function' ? onRejected : error => { throw error; };
var self = this;
var promise2;
if(self.state === 'fulfilled') {
// 状态为fulfilled时,直接执行onFulfilled,并返回新的Promise
return promise2 = new MyPromise(function(resolve, reject) {
setTimeout(function() {
try {
var x = onFulfilled(self.value);
resolvePromise(promise2, x, resolve, reject);
} catch (error) {
reject(error);
}
});
});
}
if(self.state === 'rejected') {
// 状态为rejected时,直接执行onRejected,并返回新的Promise
return promise2 = new MyPromise(function(resolve, reject) {
setTimeout(function() {
try {
var x = onRejected(self.reason);
resolvePromise(promise2, x, resolve, reject);
} catch (error) {
reject(error);
}
});
});
}
if(self.state === 'pending') {
// 状态为pending时,将onFulfilled和onRejected注册为回调函数
return promise2 = new MyPromise(function(resolve, reject) {
self.onFulfilledCallbacks.push(function(value) {
try {
var x = onFulfilled(value);
resolvePromise(promise2, x, resolve, reject);
} catch (error) {
reject(error);
}
});
self.onRejectedCallbacks.push(function(reason) {
try {
var x = onRejected(reason);
resolvePromise(promise2, x, resolve, reject);
} catch (error) {
reject(error);
}
});
});
}
};
// resolvePromise函数用于处理then方法返回值的情况
function resolvePromise(promise2, x, resolve, reject) {
if(promise2 === x) {
return reject(new TypeError('Chaining cycle detected for promise'));
}
if((typeof x === 'object' && x !== null) || typeof x === 'function') {
try {
var then = x.then;
if(then === function) {
x.then(resolve, reject);
} else if(typeof then === 'function') {
var called;
try {
then.call(x, function resolvePromiseResult(y) {
if(called) return;
called = true;
resolvePromise(promise2, y, resolve, reject);
}, function rejectPromiseResult(r) {
if(called) return;
called = true;
reject(r);
});
} catch(error) {
if(called) return;
called = true;
reject(error);
}
} else {
resolve(x);
}
} catch(error) {
reject(error);
}
} else {
resolve(x);
}
}
// 打印README.txt中的内容
const fs = require('fs');
fs.readFile('./README.txt', 'utf8', (err, data) => {
if(err) throw err;
console.log(data);
});
```
知识点九:实现Promise时的注意事项
- 确保Promise状态一旦改变就不再变化。
- 确保resolve和reject函数的正确使用,以及错误的捕获。
- 确保异步逻辑的正确处理,使得then()中的回调函数在下一个事件循环执行。
- 对于then()方法返回值的处理,需要使用resolvePromise函数来处理。
- 对于catch()方法的实现,确保其能够捕获到链中的任何错误。
以上内容将帮助开发者全面掌握手写Promise的技巧,深入理解其内部机制,并能够在实际开发中灵活应用。"
689 浏览量
2021-07-16 上传
2021-07-16 上传
230 浏览量
2021-07-14 上传
136 浏览量
2025-02-16 上传
2025-02-16 上传
![](https://profile-avatar.csdnimg.cn/default.jpg!1)
weixin_38624914
- 粉丝: 7
最新资源
- layer弹窗多按钮点击关闭功能修复方法
- Lerna-cli:打造基于Lerna的代码脚手架工具
- AB笔记本:谷歌Colab的专属代码编辑器
- spacedesk:跨平台屏幕扩展解决方案最新发布
- coconutBattery:全面监测苹果MacBook电池健康
- 快速搭建基于Vagrant和Chef-solo的RStudio服务器环境
- VMware完全卸载与清理工具教程
- WinSetView: 个性化Windows资源管理器视图设置工具
- Java科研管理平台源码与文档一体化解决方案
- 使用vim-pathogen轻松管理Vim的运行时路径
- 映泰TH61A主板BIOS更新指南
- Lame-iOS 静态库打包指南及文件结构解析
- 深度学习实战:使用卷积神经网络识别Fashion-MNIST
- 串行机器人逆运动学算法实现与Python编程
- 北航软件工程课件概览
- Access 2013数据库文档目录概览