Node.js 中的回调地狱
Posted
技术标签:
【中文标题】Node.js 中的回调地狱【英文标题】:Callback hell in Node.js 【发布时间】:2017-01-01 20:13:28 【问题描述】:我在 Node.js 中遇到了“回调地狱”的情况。
基本上我想要的是:
从静态 json 文件中读取数据(本地) --> 查询 MongoDB 以从两个单独的集合中获取两条记录 --> 比较返回的数据 -> 将比较后的结果添加到结果对象中 --> 进入下一步在循环中 --> 重复。
请检查代码,让我知道问题出在哪里。
jsonfile.readFile(file, function(err, staticData)
if(err)
console.log("Error while loading Tower Details from Static Data " + err);
else
var staticD = staticData.Teams;
var l = staticData.Teams.length;
// console.log('*******************Getting Tower Level Data from Static File*******************');
//console.log('*******************Tower Name received is ******************* ' + staticData.Tower);
if(counter == l)
console.log('Inside the couneter loop');
res.json(testObject);
for ( var i = 0 ; i<l; i++)
var trackName = staticD[i].name
console.log('Counter--------->>>>' + counter);
//console.log("Team name " + staticD[i].name);
++counter;
for (var j = 0 ; j<staticD[i].applications.length;j++)
//var RObj;
//var AObj;
//console.log("Application Name " + staticD[i].applications[j]);
var applicationName = staticD[i].applications[j];
var test = new Object();
test.data = [];
var resultSet;
var response = reference.find('appname' : applicationName , 'track' : trackName ).sort('_id': -1);
var promise = response.exec();
var alertT = alert.find('appname' : applicationName , 'track' : trackName ).sort('_id': -1).limit(1);
var promise1 = alertT.exec();
promise.then(function allRefRecords (recordAlerts)
if(recordAlerts.length >0)
//console.log('Ref Length' + recordAlerts.length);
recordAlerts.forEach(function refRecord(R)
testObject.data.testInfra.push(R);
//console.log('testObject' + testObject.data.testInfra);
);
);
promise1.then(function allAlertsRecords (alerts)
if(alerts.length > 0)
alerts.forEach(function refRecord(a)
// console.log('a' + a)
testObject.data.testCustom.push(a);
//console.log('testObject' + testObject.data.testCustom);
// res.json(testObject);
);
)
.then(function()
resultSet = compareData(testObject.data.testCustom,testObject.data.testInfra);
test.data.push(resultSet);
)
.then(function()
res.json(test);
);
);
);
【问题讨论】:
我会建议你在你的代码中使用async
,而不是使用for循环。
我已经尝试了代码中的承诺,但是我得到了可变的结果。有时我会收到 2 条记录,有时会收到 3 条记录。
【参考方案1】:
不要嵌套函数,给它们命名并将它们放在顶层 你的程序。使用功能提升来移动 功能“首屏”。处理每一个错误中的每一个错误 您的回调并使用类似标准的 linter 来帮助您 这。创建可重用的函数并将它们放在一个模块中以减少 理解代码所需的认知负荷。拆分你的 像这样将代码分成小块也可以帮助您处理错误,编写 测试,迫使您创建一个稳定且记录在案的公共 API 您的代码,并有助于重构。
来源:http://callbackhell.com/
使用异步、承诺、设计和许多其他方式可以避免回调地狱...... 但是 99% 的时间,设计是最好的(恕我直言),你不需要其他东西。
一些链接:How to Elegantly Solve the Callback HellAvoiding Callback Hell in Node.js
记住回调地狱不是致命的;)
【讨论】:
我已经在代码中尝试过承诺,现在我得到了结果。但是,结果中的记录数是随机的。这意味着有时我会收到 2 条记录,有时会收到 3 条记录,这是对同一请求的响应。我想要的是:从参考集合中获取一条记录,然后从警报集合中获取一条记录,然后比较在上一步中获取的两个对象并返回结果。我也在添加代码 sn-ps。 代码片段#1 response = reference.find('appname' : applicationName , 'track' : trackName ).sort('_id': -1);变种承诺;承诺 = response.exec();变量警报T; alertT = alert.find('appname' : applicationName , 'track' : trackName ).sort('_id': -1).limit(1);变种承诺1; promise1 = alertT.exec(); 代码片段#2 : promise.then(function allRefRecords (recordAlerts) if(recordAlerts.length == 1) recordAlerts.forEach(function refRecord(R) testObject.data.testInfra.push (R); ); ); 代码片段#3 : promise1.then(function allAlertsRecords (alerts) itemProcessed++; if(alerts.length == 1) alerts.forEach(function refRecord(a) testObject.data.testCustom .push(a); resultSet = compareData(testObject.data.testCustom,testObject.data.testInfra); returnObject.data.push(resultSet); ); if(itemProcessed == parseInt(total)) res.json (returnObject); ); 添加您在问题中尝试过的代码。【参考方案2】:一些防止进一步出现回调地狱的提示,您可以浏览下一个库:
Async.js:您可以连续执行函数而无需嵌套它们。 Bluebird:通过映射和排队,异步逻辑将更易于管理。 问:揭示了 promise 的概念,可以毫不费力地管理嵌套调用。【讨论】:
以上是关于Node.js 中的回调地狱的主要内容,如果未能解决你的问题,请参考以下文章
Node.js回调地狱及使用Promiseasync和await函数的解决方法