深入理解JavaScript状态模式与手动实现Promise
需积分: 9 157 浏览量
更新于2024-12-25
收藏 877B ZIP 举报
资源摘要信息:"js代码-状态模式 手写promise"
状态模式是一种行为设计模式,它允许对象在其内部状态改变时改变其行为。在JavaScript中,Promise是一个非常重要的异步编程模型,它使用状态模式来管理异步操作的三个状态:pending(等待中)、fulfilled(已成功)和rejected(已失败)。
在本资源中,我们将探讨如何通过状态模式手动实现一个简化版的Promise。Promise的设计允许我们注册回调函数来处理异步操作的成功和失败结果,而不需要使用回调地狱(callback hell)或者将错误处理逻辑与业务逻辑耦合在一起。
### 状态模式的核心概念
- **状态**:对象内部状态的表示,可以理解为一组属性和方法的集合。
- **上下文**:状态模式中被管理的对象,它维护一个状态实例,并把客户端请求委托给当前状态对象。
- **状态管理**:上下文通过状态管理器来切换状态,并且状态管理器负责维护状态对象。
### Promise的三个状态
Promise有三个状态,每个状态都对应一系列的行为。
1. **Pending(等待中)**:初始状态,既不是成功,也不是失败状态。
2. **Fulfilled(已成功)**:意味着操作成功完成。
3. **Rejected(已失败)**:意味着操作失败。
### 手写Promise的关键步骤
在手写Promise时,我们需要理解并实现以下关键部分:
1. **Promise构造函数**:接收一个执行器函数,这个函数有两个参数`resolve`和`reject`,分别用来改变Promise的状态为fulfilled或rejected。
2. **then方法**:用来注册成功和失败的回调函数。需要处理异步操作完成后的状态,如果状态是fulfilled,则执行成功回调,如果状态是rejected,则执行失败回调。
3. **resolve和reject函数**:这两个函数分别用来将Promise的状态从pending改变为fulfilled或rejected。
4. **链式调用**:then方法返回的是一个新的Promise实例,这样可以实现多个then方法的链式调用。
### 示例代码结构
```javascript
// main.js
class MyPromise {
// Promise的三个状态常量
static PENDING = 'pending';
static FULFILLED = 'fulfilled';
static REJECTED = 'rejected';
// Promise的初始状态
state = MyPromise.PENDING;
// 成功值
value = null;
// 失败原因
reason = null;
// 成功回调函数队列
onFulfilledCallbacks = [];
// 失败回调函数队列
onRejectedCallbacks = [];
constructor(executor) {
// 执行器函数立即执行
try {
executor(this.resolve, this.reject);
} catch (error) {
this.reject(error);
}
}
// 改变状态为fulfilled的方法
resolve = (value) => {
if (this.state === MyPromise.PENDING) {
this.state = MyPromise.FULFILLED;
this.value = value;
this.onFulfilledCallbacks.forEach(fn => fn(value));
}
}
// 改变状态为rejected的方法
reject = (reason) => {
if (this.state === MyPromise.PENDING) {
this.state = MyPromise.REJECTED;
this.reason = reason;
this.onRejectedCallbacks.forEach(fn => fn(reason));
}
}
// then方法
then(onFulfilled, onRejected) {
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value;
onRejected = typeof onRejected === 'function' ? onRejected : reason => { throw reason };
// 返回一个新Promise
return new MyPromise((resolve, reject) => {
if (this.state === MyPromise.FULFILLED) {
// 异步执行onFulfilled
setTimeout(() => {
try {
const x = onFulfilled(this.value);
this.resolvePromise(x, resolve, reject);
} catch (error) {
reject(error);
}
}, 0);
} else if (this.state === MyPromise.REJECTED) {
// 异步执行onRejected
setTimeout(() => {
try {
const x = onRejected(this.reason);
this.resolvePromise(x, resolve, reject);
} catch (error) {
reject(error);
}
}, 0);
} else if (this.state === MyPromise.PENDING) {
// 状态未定,先缓存回调函数
this.onFulfilledCallbacks.push((value) => {
setTimeout(() => {
try {
const x = onFulfilled(value);
this.resolvePromise(x, resolve, reject);
} catch (error) {
reject(error);
}
}, 0);
});
this.onRejectedCallbacks.push((reason) => {
setTimeout(() => {
try {
const x = onRejected(reason);
this.resolvePromise(x, resolve, reject);
} catch (error) {
reject(error);
}
}, 0);
});
}
});
}
// 解析then回调函数返回的值x
resolvePromise(x, resolve, reject) {
// x为null或非对象,直接resolve
if (x === null || typeof x !== 'object' && typeof x !== 'function') {
return resolve(x);
}
// 防止循环引用
let called;
try {
const then = x.then;
if (typeof then === 'function') {
then.call(
x,
y => {
if (called) return;
called = true;
this.resolvePromise(y, resolve, reject);
},
r => {
if (called) return;
called = true;
reject(r);
}
);
} else {
resolve(x);
}
} catch (error) {
if (called) return;
called = true;
reject(error);
}
}
}
// README.txt
// 该README文件包含了如何使用手写的Promise对象以及如何测试其功能。
// 用户可以通过创建Promise实例来执行异步代码,并通过then方法来处理异步操作的结果。
```
### 知识点总结
- 状态模式是一种行为设计模式,它允许对象在内部状态改变时改变其行为。
- JavaScript中的Promise对象使用状态模式来管理异步操作的三种状态:pending(等待中)、fulfilled(已成功)和rejected(已失败)。
- 手写Promise涉及理解Promise的构造函数、resolve和reject方法、then方法的实现以及链式调用的原理。
- Promise的then方法可以接受两个参数,分别对应异步操作成功和失败时的回调函数。
- Promise的链式调用允许我们按照顺序执行多个异步操作,并且每个then方法的回调函数返回的结果可以传递到下一个then方法的回调函数中。
- 在手写Promise时,需要处理异步操作的状态改变,并且考虑到如何处理异步回调函数中的返回值,以及如何实现状态的正确转换。
通过以上内容的学习,开发者可以更好地理解JavaScript中Promise的工作机制,并且能够手动实现一个符合Promises/A+规范的Promise对象,这对于深入掌握异步编程和JavaScript语言特性非常有帮助。
2021-07-14 上传
2021-07-16 上传
2023-11-10 上传
2020-11-21 上传
点击了解资源详情
点击了解资源详情
点击了解资源详情
点击了解资源详情
2021-04-07 上传