什么是 Promise?
简单来说,Promise 是一个表示异步操作最终完成或失败的对象。它就像现实生活中的"承诺"——你现在得到一个承诺,将来这个承诺要么被兑现(成功),要么被拒绝(失败)。
在 ES6 之前,我们处理异步操作主要依赖回调函数,这很容易导致"回调地狱"。Promise 的出现就是为了解决这个问题,它提供了一种更优雅的方式来处理异步操作。
Promise 的三种状态
每个 Promise 都有三种可能的状态:
- pending(等待中) :初始状态,既不是成功,也不是失败
- fulfilled(已兑现) :操作成功完成
- rejected(已拒绝) :操作失败
一旦 Promise 从 pending 变为 fulfilled 或 rejected,状态就固定了,不会再改变。
基本用法
让我们看一个简单的 Promise 示例:
const myFirstPromise = new Promise((resolve, reject) => {
// 这里执行异步操作
setTimeout(() => {
if (Math.random() > 0.5) {
resolve("成功!我拿到了数据");
} else {
reject(new Error("失败!出了点问题"));
}
}, 1000);
});
myFirstPromise
.then((result) => {
console.log(result); // 成功时执行
})
.catch((error) => {
console.error(error); // 失败时执行
});
在这个例子中,我们创建了一个 Promise,它会在 1 秒后随机决定是成功还是失败。通过 .then()
处理成功情况,.catch()
处理失败情况。
Promise 链
Promise 最强大的特性之一是链式调用,这让我们可以优雅地处理多个异步操作:
function getUserData(userId) {
return new Promise((resolve) => {
setTimeout(() => resolve({ id: userId, name: "张三" }), 500);
});
}
function getUserPosts(userId) {
return new Promise((resolve) => {
setTimeout(() => resolve(["文章1", "文章2"]), 500);
});
}
getUserData(123)
.then((user) => {
console.log("获取用户数据:", user);
return getUserPosts(user.id);
})
.then((posts) => {
console.log("获取用户文章:", posts);
})
.catch((error) => {
console.error("发生错误:", error);
});
常用静态方法
Promise 提供了一些有用的静态方法:
-
Promise.all() :等待所有 Promise 完成,或任一 Promise 失败
Promise.all([promise1, promise2, promise3])
.then((results) => {
console.log(results); // 所有 Promise 的结果数组
})
.catch((error) => {
console.error(error); // 任一 Promise 失败
});
2.Promise.race() :返回最先完成的 Promise(无论成功或失败)
Promise.race([promise1, promise2])
.then((result) => {
console.log(result); // 最先完成的 Promise 的结果
});
3.Promise.allSettled() :等待所有 Promise 完成(无论成功或失败)
Promise.allSettled([promise1, promise2])
.then((results) => {
results.forEach((result) => {
if (result.status === "fulfilled") {
console.log("成功:", result.value);
} else {
console.log("失败:", result.reason);
}
});
});
常见误区
-
忘记返回 Promise:在 then 链中,如果忘记 return,下一个 then 会立即执行
// 错误示例
somePromise()
.then((result) => {
anotherPromise(); // 忘记 return
})
.then((result) => {
// 这里的 result 是 undefined
});
-
-
错误处理不当:catch 应该放在链的末尾,或者适当位置处理特定错误
-
Promise 构造函数中使用 try/catch:Promise 构造函数会自动捕获异常
-
// 不必要的 try/catch
new Promise((resolve, reject) => {
try {
// 代码
} catch (error) {
reject(error);
}
});
// 可以简化为
new Promise((resolve, reject) => {
// 代码,错误会自动被捕获
});
实际应用示例
让我们看一个更实际的例子,模拟用户登录流程:
function login(username, password) {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (username === "admin" && password === "123456") {
resolve({ token: "abc123", userId: 1 });
} else {
reject(new Error("用户名或密码错误"));
}
}, 1000);
});
}
function getUserProfile(token, userId) {
return new Promise((resolve) => {
setTimeout(() => {
resolve({
name: "我",
avatar: "https://example.com/avatar.jpg",
email: "me@example.com"
});
}, 800);
});
}
login("admin", "123456")
.then((authData) => {
console.log("登录成功,获取token:", authData.token);
return getUserProfile(authData.token, authData.userId);
})
.then((profile) => {
console.log("获取用户资料:", profile);
})
.catch((error) => {
console.error("登录流程出错:", error.message);
});
总结
Promise 是现代 JavaScript 异步编程的基石,理解它的工作原理对于编写可维护的异步代码至关重要。记住:
- Promise 有三种状态:
pending、fulfilled、rejected
- 使用 .then() 处理成功,.catch() 处理失败
- Promise 链可以优雅地处理多个异步操作
- 注意常见陷阱,如忘记返回 Promise
- 合理使用 Promise 静态方法处理多个 Promise
掌握了 Promise,你就为学习更高级的 async/await 语法打下了坚实基础。希望这篇文章能帮助你更好地理解和运用 Promise!