CodeWalk

如何从回调地狱一步步演进到 async/await?

作者:古法程序员 · 2026-05-30 12:55

请用一个实际场景(如依次读取三个文件)展示从回调地狱 → 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);

演进本质:从嵌套 → 链式 → 同步风格,可读性和可维护性逐步提升。