返回
JavaScript的承诺让你我相约,让这世界精彩绽放
前端
2023-09-03 01:11:27
深入理解Promise
在前端开发中,处理异步操作是一项常见的任务。从HTTP请求到本地存储访问,无处不在。Promise提供了一种更加灵活且易于管理的方式来处理这些异步操作。它代表了一个还未完成的计算,并可以注册回调函数,从而在未来某个时间点得到结果或异常。
Promise的核心概念
- 状态:一个Promise有三种状态——未定态(pending)、已成功态(fulfilled)和已失败态(rejected)。一旦状态确定,就不会再改变。
- 值/原因:当Promise完成时,它会有一个值或错误原因。如果Promise已经成功,则该值为结果;如果已被拒绝,则这个值是导致其被拒绝的原因。
- then方法:通过
.then()
可以注册处理成功的回调函数和失败的回调函数。
Promise的基本用法
const promise = new Promise((resolve, reject) => {
// 异步操作,比如setTimeout或者fetch等
setTimeout(() => {
const data = "数据加载成功";
resolve(data); // 成功时调用resolve,传递结果
}, 1000);
});
promise.then(
(result) => console.log(result),
(error) => console.error(error)
);
手写Promise实现
深入理解了基本概念后,不妨尝试手动实现一个简单的Promise。
完整的手写代码示例
class MyPromise {
constructor(executor) {
this.state = 'pending'; // 初始状态是未定态
this.value = undefined; // 成功或失败的结果值
this.onFulfilledCallbacks = []; // 存储成功的回调函数
this.onRejectedCallbacks = []; // 存储失败的回调函数
const resolve = (value) => {
if(this.state === 'pending') {
this.value = value;
this.state = 'fulfilled';
setTimeout(() => { // 确保所有.then方法异步执行
this.onFulfilledCallbacks.forEach(callback => callback(value));
});
}
};
const reject = (reason) => {
if(this.state === 'pending') {
this.value = reason;
this.state = 'rejected';
setTimeout(() => { // 确保所有.then方法异步执行
this.onRejectedCallbacks.forEach(callback => callback(reason));
});
}
};
try {
executor(resolve, reject);
} catch (error) {
reject(error);
}
}
then(onFulfilled, onRejected) {
return new MyPromise((resolve, reject) => {
if(this.state === 'fulfilled') {
setTimeout(() => {
try {
const result = onFulfilled ? onFulfilled(this.value) : this.value;
resolve(result);
} catch (error) {
reject(error);
}
});
}
if(this.state === 'rejected') {
setTimeout(() => {
try {
const result = onRejected ? onRejected(this.value) : this.value;
resolve(result); // 注意这里使用resolve,因为onRejected返回的是成功结果
} catch (error) {
reject(error);
}
});
}
if(this.state === 'pending') {
this.onFulfilledCallbacks.push((value) => {
setTimeout(() => {
try {
const result = onFulfilled ? onFulfilled(value) : value;
resolve(result);
} catch (error) {
reject(error);
}
});
});
this.onRejectedCallbacks.push((reason) => {
setTimeout(() => {
try {
const result = onRejected ? onRejected(reason) : reason;
resolve(result); // 注意这里使用resolve,因为onRejected返回的是成功结果
} catch (error) {
reject(error);
}
});
});
}
});
}
static resolve(value) {
return new MyPromise(resolve => resolve(value));
}
static reject(reason) {
return new MyPromise((_, reject) => reject(reason));
}
}
使用手写Promise
const myPromise = new MyPromise((resolve, reject) => {
setTimeout(() => {
if(true) { // 模拟成功情况
resolve("成功");
} else {
reject(new Error("失败"));
}
}, 1000);
});
myPromise.then(
(result) => console.log(result),
(error) => console.error(error)
);
MyPromise.resolve("直接成功").then(console.log);
MyPromise.reject(new Error("直接拒绝")).catch(console.error); // 注意使用.catch()
安全建议
- 使用try-catch包裹异步操作,避免意外错误中断执行。
- 在链式调用中谨慎处理error,确保每个
.then()
都有对应的.catch()
或在链末尾添加catch()
来捕捉可能的错误。
通过理解和实现Promise,开发者可以更好地掌握JavaScript中的异步编程机制,从而编写出更加高效和易于维护的代码。