JavaScript 教程:深入理解 Promise 链式调用
什么是 Promise 链式调用
Promise 链式调用是处理异步操作序列的强大模式。它允许我们将多个异步操作按顺序连接起来,每个操作在前一个操作完成后执行,同时将结果传递给下一个操作。
基础 Promise 链示例
让我们从一个简单例子开始:
new Promise(function(resolve) {
setTimeout(() => resolve(1), 1000);
})
.then(function(result) {
console.log(result); // 1
return result * 2;
})
.then(function(result) {
console.log(result); // 2
return result * 2;
})
.then(function(result) {
console.log(result); // 4
});
执行流程解析:
- 初始 Promise 在1秒后解析为1
- 第一个
.then()
接收1,返回2 - 第二个
.then()
接收2,返回4 - 第三个
.then()
接收4并输出
常见误区:多个处理程序 vs 链式调用
初学者常犯的错误是将多个.then()
附加到同一个 Promise 上,误以为这会形成链式调用:
let promise = new Promise(function(resolve) {
setTimeout(() => resolve(1), 1000);
});
promise.then(function(result) {
console.log(result); // 1
});
promise.then(function(result) {
console.log(result); // 1
});
这实际上创建了多个独立的处理程序,它们都接收相同的初始值1,而不是形成传递结果的链。
返回 Promise 的高级链式调用
.then()
处理程序可以返回新的 Promise,使链式调用能够处理异步操作序列:
new Promise(function(resolve) {
setTimeout(() => resolve(1), 1000);
})
.then(function(result) {
console.log(result); // 1
return new Promise(resolve => {
setTimeout(() => resolve(result * 2), 1000);
});
})
.then(function(result) {
console.log(result); // 2
});
这种模式特别适合需要顺序执行的异步操作,如:
- 文件加载
- API请求
- 数据库操作
实际应用:脚本加载器
假设我们有一个loadScript
函数返回 Promise,我们可以优雅地加载多个脚本:
loadScript("one.js")
.then(() => loadScript("two.js"))
.then(() => loadScript("three.js"))
.then(() => {
// 所有脚本加载完成后执行
one();
two();
three();
});
Fetch API 的链式调用实践
Fetch API 是 Promise 链式调用的典型应用场景:
fetch('/user.json')
.then(response => response.json())
.then(user => fetch(`https://api.github.com/users/${user.name}`))
.then(response => response.json())
.then(githubUser => {
// 显示用户头像
let img = document.createElement('img');
img.src = githubUser.avatar_url;
document.body.append(img);
return githubUser;
})
.then(githubUser => {
console.log(`完成显示 ${githubUser.name} 的头像`);
});
处理异步操作的技巧
当需要在异步操作完成后执行其他操作时,应该返回新的 Promise:
.then(githubUser => {
return new Promise(resolve => {
// 显示头像
setTimeout(() => {
// 移除头像
resolve(githubUser); // 传递数据给下一个处理程序
}, 3000);
});
})
代码组织最佳实践
将逻辑拆分为可重用的函数:
function loadJson(url) {
return fetch(url).then(response => response.json());
}
function loadUser(name) {
return fetch(`/users/${name}`).then(response => response.json());
}
function showAvatar(user) {
return new Promise(resolve => {
// 显示和隐藏头像的逻辑
resolve(user);
});
}
// 使用组合
loadJson('/user.json')
.then(user => loadUser(user.name))
.then(showAvatar)
.then(user => console.log(`显示完成: ${user.name}`));
总结要点
- Promise 链式调用通过
.then()
方法连接多个异步操作 - 每个
.then()
可以返回普通值或新的 Promise - 返回 Promise 会暂停链式调用直到该 Promise 解决
- 合理拆分逻辑到函数中可以提高代码可读性和复用性
- 避免将多个
.then()
附加到同一个 Promise 上形成伪链式
Promise 链式调用是现代 JavaScript 异步编程的核心模式,掌握它对于编写清晰、可维护的异步代码至关重要。
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考