📜  什么是回调地狱以及如何在 Node.js 中避免它?

📅  最后修改于: 2022-05-13 01:56:17.364000             🧑  作者: Mango

什么是回调地狱以及如何在 Node.js 中避免它?

在本文中,我们将了解回调地狱以及如何避免它。回调地狱是我们有复杂的嵌套回调的情况。正如我们已经提到过“回调”这个术语,所以在深入了解回调地狱的细节之前,让我们先了解一下回调是什么?回调是在完成特定任务时自动调用的函数。基本上,它允许程序运行其他代码,直到某个任务没有完成。此函数允许您执行大量可由操作系统处理的 I/O 操作,而无需等待任何 I/O 操作完成,这使得 nodeJs 具有高度可扩展性。

句法:

const fs = require("fs");
fs.readFile("file_path", "utf8", function (err, data) {
    if (err) {
        // Handle the error  
    } else {
        // Process the file text given with data
    }
});

什么是回调地狱?

Node.js 中的回调地狱是我们有复杂的嵌套回调的情况。在这种情况下,每个回调都接受作为先前回调的结果而获得的参数。这样,代码结构看起来像金字塔,可读性差,维护难度大。此外,如果一个函数出现错误,那么所有其他函数都会受到影响。

创建结构:

第 1 步:首先,使用以下文本创建一个文本文件 input.txt:

Welcome to GFG.
Learn NodeJS with GeeksforGeeks

第 2 步:现在,创建一个名为 main.js 的 javascript 文件。

项目结构:

女朋友

示例:这是回调地狱的一个简单示例。我们可以看到代码中有嵌套的回调,这使得代码更难理解。

Javascript
var fs = require("fs");
var textFile = "input.txt";
fs.exists(textFile, function (exists) {
    if (exists) {
        fs.stat(textFile, function (err, res) {
            if (err) {
                throw err;
            }
            if (res.isFile()) {
                fs.readFile(textFile, 
                    "utf-8", function (err, data) {
                    if (err) {
                        throw err;
                    }
                    console.log(data);
                });
            }
        });
    }
});


Javascript
var fs = require('fs');
const fsPromises = require('fs').promises;
fs.promises.readFile("input.txt")
    .then(function (data) {
        console.log("" + data);
    })
    .catch(function (error) {
        console.log(error);
    })


运行服务器:现在运行 main.js 以使用以下命令查看结果:

node main.js

输出:

在这个例子中,我们有一个 nodeJS 的 fs 模块,它提供了文件 I/O 操作的功能。借助 exists()函数,我们可以测试给定路径是否存在于文件系统中。如果它存在,我们在其中定义了一个函数。因此在这个例子中,我们在另一个函数中定义函数,这给我们带来了回调地狱问题,因为它很难理解和阅读代码。

如何避免“回调地狱”?

  • Promise:在 Promise 的帮助下,可以避免回调地狱。 javascript 中的 Promise 是在 Node.js 中处理异步操作的一种方式。它允许我们从异步函数(如同步函数)返回一个值。当我们从异步方法返回某些内容时,它会返回一个 Promise,当它在未来可用时,可以在 then() 方法或异步函数内部的 await 的帮助下使用该最终值。下面提到了创建 Promise 的语法。

句法:

const promise = new Promise(function (resolve, reject) {
    // code logic
});

示例:在这个示例中,我们正在借助 Promise 读取名为“input.txt”的纺织品。创建一个 javascript 文件名 main.js 并编写以下代码:

Javascript

var fs = require('fs');
const fsPromises = require('fs').promises;
fs.promises.readFile("input.txt")
    .then(function (data) {
        console.log("" + data);
    })
    .catch(function (error) {
        console.log(error);
    })

运行服务器:现在运行 main.js 以使用以下命令查看结果:

node main.js

输出:

在这个例子中,我们有一个 nodeJS 的 fs 模块,它提供了文件 I/O 操作的功能。然后我们在 fs.promises.readfile 方法的帮助下读取文件,该方法返回一个 promise。

  • Async.js:另一种避免回调地狱的方法是,我们有一个名为 Async 的 npm 模块。 Async 有助于管理异步 JavaScript。一些有用的异步方法是串行、并行、瀑布等。它也适用于浏览器。

安装:

npm i async
  • 为了避免回调,我们应该避免在程序中使用两个以上的嵌套回调函数,因为这将有助于保持代码的可读性。