有什么常见的做法可以避免在使用错误返回异步函数时在Node.JS中发生回调地狱?

时间:2018-09-11 14:01:22

标签: javascript node.js asynchronous callback

我是Node的新手,并且现在尝试不使用第三方npm软件包来练习纯Node脚本。我遇到的第一个问题是我的代码开始看起来像> 符号。我的意思是我在回调内部的回调内部有回调,依此类推……

fs.open(‘filename.json’, 'wx', (error, fileDescriptor) => {
  if (!error && fileDescriptor) {
    // Do something with the file here ...
    fs.writeFile(fileDescriptor, newData, (error) => {
      if (!error) {
        fs.close(fileDescriptor, (error) => {
          if (!error) {
            callback(false);
          } else {
            callback('Error closing the file');
          }
        });
      } else {
        callback('Error writing to new file');
      }
    });
  } else {
    callback('Could not create new file, it may already exists');
  }
});

这是一个简单的示例,但是我们可能具有更复杂的逻辑,其中可能包括更多的异步步骤,因此回调的层次也更深。尽管在上面的示例中使用了fs模块,但查询仍然更加通用。使用其他模块(即zlib.gzip(str, callback))时,我们可能会遇到这种回调情况。

所以我的问题是我们是否有任何常见的做法来避免这种内部回调的代码,使其看起来更直接,更易读,同时又保持异步?

我想可以将代码拆分为更精细的模块,并且在同一位置没有太多的多级异步逻辑。我还猜想有一些像async这样的软件包可能对此有所帮助。但是,仍然有任何通用的语言实践/结构可以使这种内部回调回调代码更加平坦,而无需使用外部帮助程序吗?

1 个答案:

答案 0 :(得分:2)

防止内部回调的一种方法是(如注释线程中所述)使用 Promise async / await语句。这将使异步代码结构更加平坦。为此,可以使用方便的util.promisify(original)函数。它使我们能够从回调切换到承诺。看看下面带有fs函数的示例:

// Dependencies.
const util = require('util');
const fs = require('fs');

// Promisify "error-back" functions.
const fsOpen = util.promisify(fs.open);
const fsWrite = util.promisify(fs.writeFile);
const fsClose = util.promisify(fs.close);

// Now we may create 'async' function with 'await's.
async function doSomethingWithFile(fileName) {
  const fileDescriptor = await fsOpen(fileName, 'wx');
  
  // Do something with the file here...
  
  await fsWrite(fileDescriptor, newData);
  await fsClose(fileDescriptor);
}