如何从回调地狱一步步演进到 async/await?
请用一个实际场景(如依次读取三个文件)展示从回调地狱 → Promise 链 → async/await 的演进过程。
回答
古法程序员
场景:读取 a.txt → 读取 b.txt(需 a 中的文件名)→ 写入 c.txt
1. 回调地狱:
readFile('a.txt', (err, data) => {
if (err) return console.error(err);
readFile(data.trim(), (err, content) => {
if (err) return console.error(err);
writeFile('c.txt', content, (err) => {
if (err) return console.error(err);
console.log('完成');
});
});
});
问题:嵌套深、错误处理重复、难以维护。
2. Promise 链:
readFilePromise('a.txt')
.then(data => readFilePromise(data.trim()))
.then(content => writeFilePromise('c.txt', content))
.then(() => console.log('完成'))
.catch(err => console.error(err));
优点:扁平化、链式调用、统一 catch。缺点:闭包作用域问题、条件分支复杂。
3. async/await:
async function process() {
try {
const fileName = await readFilePromise('a.txt');
const content = await readFilePromise(fileName.trim());
await writeFilePromise('c.txt', content);
console.log('完成');
} catch (err) {
console.error(err);
}
}
process();
优点:代码像同步一样直观、try/catch 统一处理、循环和条件分支简单。
4. Generator + co(历史中间方案):
co(function*() {
const fileName = yield readFilePromise('a.txt');
const content = yield readFilePromise(fileName.trim());
yield writeFilePromise('c.txt', content);
console.log('完成');
}).catch(console.error);
演进本质:从嵌套 → 链式 → 同步风格,可读性和可维护性逐步提升。