回调地狱和重构

Callback Hell and Refactoring

我一直在学习 JavaScript 并开始探索 Node.我花了很多时间了解回调地狱以及如何修复它,但现在我比以往任何时候都更加迷茫,我开始认为我正在倒着看它(这可能是一个愚蠢的问题)。我已阅读有关 callbackhell.com 的指南,第 1 条规则是保持代码浅薄。

这里是连接到数据库,然后读取文件,然后将记录插入到 MongoDB 然后记录日志的示例:

MongoClient.connect(url, (err, db)=>{
   let dbo = db.db('test');
   fs.readFile('./data.json', (err, data)=>{
       let records = JSON.parse(data);
       dbo.collection('people').insertMany(records, (err, result) =>{
              console.log("result");
              db.close();
      })
   });
});

在示例中,我有 3 个匿名回调函数,但我不知道如何重构,因为在整个回调过程中都使用了数据库。据我了解,我应该瞄准 3 个命名函数(或者我遗漏了什么?)并这样称呼它:

MongoClient.connect(url, cb1);

和类似这样的功能:

function cb1(err, db){
let dbo = db.db('test');
fs.readFile('./data.json', cb2);

}

function cb2(err, data){
    let records = JSON.parse(data);
    // ??? dbo.collection('people).insertMany(records, cb3)
    //now what?
}

function cb3(err, result){
    console.log(result);
    // ??? db.close?
}

寻找有关回调地狱的任何见解。这是回调地狱吗?我该怎么做?我在概念上错过了什么吗?它是否应该重构?

PS。 Promises 和 Async/Await 可以等到我了解如何使用回调进行异步编程

谢谢!

回调的嵌套就是通常所说的回调地狱

您尝试将回调分离为命名函数的尝试很好,但您已经意识到一个问题:您需要在所有回调中引用 db 对象,但它不存在。

您可以通过将 this 绑定到 db 或绑定一个(第一个)参数以将 db 对象作为参数传递来解决此问题。原理真的是一样的

下面是将 this 绑定到 db 对象时的样子:

function cb1(err, db) {
    let dbo = db.db('test');
    fs.readFile('./data.json', cb2.bind(db));
}

function cb2(err, data) {
    let records = JSON.parse(data);
    this.collection('people').insertMany(records, cb3.bind(this));
}

function cb3(err, result) {
    console.log(result);
    this.close();
}

下面是使用额外参数时的样子:

function cb1(err, db) {
    let dbo = db.db('test');
    fs.readFile('./data.json', cb2.bind(null, db));
}

function cb2(db, err, data) {
    let records = JSON.parse(data);
    db.collection('people').insertMany(records, cb3.bind(null, db));
}

function cb3(db, err, result) {
    console.log(result);
    db.close();
}

下一步将是接受承诺和 async await 语法。例如参见 [​​=20=].