回调地狱和重构
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=].
我一直在学习 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=].