JavaScript中Promise详解
Promise 是 JavaScript 中用于处理异步操作的对象。它代表一个异步操作的最终完成及其结果值。Promise 提供了一种更优雅的方式来处理异步代码,避免了传统的回调地狱。
1. Promise 的基本概念
Promise 有三种状态:
1. Pending(等待中):初始状态,既不是成功,也不是失败;
2. Fulfilled(已成功):操作成功完成;
3. Rejected(已失败):操作失败;
Promise 的状态一旦改变,就不会再变。即从 Pending 变为 Fulfilled 或 Rejected 后,状态就固定了。
2. 创建 Promise
你可以通过 new Promise() 构造函数来创建一个 Promise 对象。构造函数接受一个函数作为参数,这个函数有两个参数:resolve 和 reject,它们都是函数。
1. resolve(value):将 Promise 的状态从 Pending 变为 Fulfilled,并将 value 作为成功的结果;
2. reject(reason):将 Promise 的状态从 Pending 变为 Rejected,并将 reason 作为失败的原因;
const myPromise = new Promise((resolve, reject) => {
setTimeout(() => {
const success = true;
if (success) {
resolve("操作成功!");
} else {
reject("操作失败!");
}
}, 1000);
})
3. 使用 Promise
Promise 对象有两个主要的方法来处理成功和失败的情况:.then() 和 .catch()。
1. .then(onFulfilled, onRejected):当 Promise 状态变为 Fulfilled 时,调用 onFulfilled 函数;当状态变为 Rejected 时,调用 onRejected 函数;
2. .catch(onRejected):当 Promise 状态变为 Rejected 时,调用 onRejected 函数;
myPromise
.then((result) => {
console.log(result); // 输出: 操作成功!
})
.catch((error) => {
console.error(error); // 输出: 操作失败!
});
4. Promise 链式调用
Promise 支持链式调用,即在一个 .then() 中返回一个新的 Promise,然后可以在下一个 .then() 中继续处理。
new Promise((resolve, reject) => {
setTimeout(() => resolve(1), 1000);
})
.then((result) => {
console.log(result); // 输出: 1
return result * 2;
})
.then((result) => {
console.log(result); // 输出: 2
return result * 2;
})
.then((result) => {
console.log(result); // 输出: 4
});
5. Promise 的静态方法
Promise 还提供了一些静态方法来处理多个 Promise 对象:
1. Promise.all(iterable):接受一个 Promise 对象的数组,当所有 Promise 都成功时,返回一个包含所有结果的数组;如果有一个 Promise 失败,则立即返回失败的结果;
Promise.all([promise1, promise2, promise3])
.then((results) => {
console.log(results); // 所有 Promise 成功的结果数组
})
.catch((error) => {
console.error(error); // 第一个失败的 Promise 的错误
});
2. Promise.race(iterable):接受一个 Promise 对象的数组,返回第一个完成(无论成功或失败)的 Promise 的结果;
Promise.race([promise1, promise2, promise3])
.then((result) => {
console.log(result); // 第一个完成的 Promise 的结果
})
.catch((error) => {
console.error(error); // 第一个失败的 Promise 的错误
});
3. Promise.resolve(value):返回一个以给定值解析的 Promise 对象;
Promise.resolve("成功").then((result) => {
console.log(result); // 输出: 成功
});
4. Promise.reject(reason):返回一个以给定原因拒绝的 Promise 对象;
Promise.reject("失败").catch((error) => {
console.error(error); // 输出: 失败
});
6. 手写 Promise 实现
下面是一个手写的简单 Promise 实现,包含了 resolve 和 reject 的基本功能。这个实现是一个简化版,仅用于理解 Promise 的核心原理,并不完全符合官方 Promise 的规范。
class MyPromise {
constructor(executor) {
this.status = 'pending'; // 初始状态为 pending
this.value = undefined; // 存储成功的结果
this.reason = undefined; // 存储失败的原因
this.onFulfilledCallbacks = []; // 存储成功的回调函数
this.onRejectedCallbacks = []; // 存储失败的回调函数
// resolve 函数
const resolve = (value) => {
if (this.status === 'pending') {
this.status = 'fulfilled'; // 状态改为 fulfilled
this.value = value; // 存储成功的结果
// 执行所有成功的回调
this.onFulfilledCallbacks.forEach((fn) => fn());
}
};
// reject 函数
const reject = (reason) => {
if (this.status === 'pending') {
this.status = 'rejected'; // 状态改为 rejected
this.reason = reason; // 存储失败的原因
// 执行所有失败的回调
this.onRejectedCallbacks.forEach((fn) => fn());
}
};
// 执行 executor,传入 resolve 和 reject
try {
executor(resolve, reject);
} catch (error) {
reject(error); // 如果 executor 抛出异常,直接 reject
}
}
// then 方法
then(onFulfilled, onRejected) {
if (this.status === 'fulfilled') {
// 如果状态已经是 fulfilled,直接执行 onFulfilled
onFulfilled(this.value);
} else if (this.status === 'rejected') {
// 如果状态已经是 rejected,直接执行 onRejected
onRejected(this.reason);
} else if (this.status === 'pending') {
// 如果状态是 pending,将回调函数存储起来
this.onFulfilledCallbacks.push(() => onFulfilled(this.value));
this.onRejectedCallbacks.push(() => onRejected(this.reason));
}
}
// catch 方法
catch(onRejected) {
return this.then(null, onRejected);
}
}
6.1. 使用示例
// 创建一个 MyPromise
const myPromise = new MyPromise((resolve, reject) => {
setTimeout(() => {
const success = true;
if (success) {
resolve("操作成功!");
} else {
reject("操作失败!");
}
}, 1000);
});
// 使用 then 和 catch 处理结果
myPromise
.then((result) => {
console.log(result); // 输出: 操作成功!
})
.catch((error) => {
console.error(error); // 输出: 操作失败!
});
6.2. 功能说明
1. 状态管理
status 用于记录当前 Promise 的状态,初始为 pending。
当调用 resolve 时,状态变为 fulfilled,并存储成功的结果 value。
当调用 reject 时,状态变为 rejected,并存储失败的原因 reason。
2. 回调队列
如果 Promise 的状态是 pending,则将 then 中的回调函数存储到 onFulfilledCallbacks 或 onRejectedCallbacks 中。
当状态改变时,依次执行对应的回调函数。
3. 异常处理
如果 executor 函数中抛出异常,会直接调用 reject。
4. 链式调用
当前实现是一个简化版,不支持链式调用(即 then 返回一个新的 Promise)。完整的 Promise 实现需要支持链式调用。
6.3. 进一步优化
如果需要实现完整的 Promise 功能,还需要支持以下特性:
1. 链式调用:then 方法需要返回一个新的 Promise;
2. 值穿透:如果 then 的参数不是函数,需要实现值穿透;
3. 微任务队列:then 的回调函数需要放入微任务队列中执行(可以使用 queueMicrotask 或 setTimeout 模拟);
7. async/await
async/await 是 ES2017 引入的语法糖,用于更简洁地处理 Promise。async 函数返回一个 Promise,而 await 用于等待 Promise 的完成
async function myAsyncFunction() {
try {
const result = await myPromise;
console.log(result); // 输出: 操作成功!
} catch (error) {
console.error(error); // 输出: 操作失败!
}
}
myAsyncFunction();
8. 总结
Promise 是 JavaScript 中处理异步操作的重要工具。它通过 .then() 和 .catch() 方法提供了更清晰的代码结构,避免了回调地狱。async/await 进一步简化了 Promise 的使用,使得异步代码看起来更像同步代码。掌握 Promise 的使用对于编写现代 JavaScript 应用程序至关重要。