gpt4 book ai didi

node.js - 如何处理 for 循环中的回调(Node.JS)

转载 作者:太空宇宙 更新时间:2023-11-04 02:58:00 25 4
gpt4 key购买 nike

我正在尝试使用 NodeJS 编写代码,从外部 API 获取数据,然后使用 Mongoose 将它们填充到 MongoDB 中。在此期间,我将检查 Mongo 中是否已存在该特定内容。下面是我的代码。

router.route('/report') // the REST api address
.post(function(req, res) // calling a POST
{
console.log('calling report API');
var object = "report/" + reportID; // related to the API
var parameters = '&limit=100' // related to the API
var url = link + object + apiKey + parameters; // related to the API

var data = "";
https.get(url, function callback(response)
{
response.setEncoding("utf8");
response.on("data", function(chunk)
{
data += chunk.toString() + "";
});

response.on("end", function()
{
var jsonData = JSON.parse(data);
var array = jsonData['results']; // data is return in array of objects. accessing only a particular array
var length = array.length;
console.log(length);

for (var i = 0; i < length; i++)
{
var report = new Report(array.pop()); // Report is the schema model defined.
console.log('^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^');
console.log(i);
console.log('*****************************');
console.log(report);
console.log('*****************************');
// console.log(report['id']);

/*report.save(function(err)
{
if(err)
res.send(err);
});*/

Report.find({id:report['id']}).count(function(err, count) // checks if the id of that specific data already exists in Mongo
{
console.log(count);
console.log('*****************************');
if (count == 0) // if the count = 0, meaning not exist, then only save
{
report.save(function(err)
{
console.log('saved');
if(err)
res.send(err);
});
}
});
};
res.json({
message: 'Grabbed Report'
});
});
response.on("error", console.error);
});
})

我的问题是,由于 NodeJS 回调是并行的,因此它不会被顺序调用。我的最终结果是这样的:

  1. 调用报告API
  2. console.log(长度) = 100
  3. ^^^^^^^^^^^^^^^^^^^^^^^^^
  4. console.log(i) = 以 0 开头
  5. ************************************
  6. console.log(report) = 将存储在 Mongo 中的数据
  7. ************************************
  8. 数字 3 - 7 重复 100 次,长度等于 100
  9. console.log(count) = 0 或 1
  10. 数字 9 重复 100 次
  11. console.log('已保存')
  12. 数字 11 重复 100 次
  13. 最后,仅将 100 条数据中的最后一个存储到 Mongo

我需要的是某种技术或方法来处理这些回调,这些回调一个接一个地执行,而不是按顺序跟随循环。我很确定这是问题所在,因为我的其他 REST API 都正常工作。

我研究了异步方法、 promise 、递归函数和其他一些我真正理解如何解决这个问题的方法。我真的希望有人能够对这个问题有所了解。

如果我提问的方式有任何错误,请随时纠正我。这是我在 StackOverflow 上发布的第一个问题。

最佳答案

这个问题被称为 "callback hell" 。还有很多其他方法,例如使用 PromiseAsync您会找到的库。

我对原生的 async ES7 更兴奋会带来,您今天实际上可以开始使用转译器库 Babel .

但到目前为止,我发现的最简单的方法如下:您取出长回调函数并在外部定义它们。

router.route('/report') // the REST api address
.post(calling_a_POST)

function calling_a_POST(req, res) {
...
var data = "";
https.get(url, function callback(response) {
...
response.on("end", response_on_end_callback); // --> take out
response.on("error", console.error);
});
}

function response_on_end_callback() { // <-- define here
...
for (var i = 0; i < length; i++) {
var report = new Report(array.pop());
...
Report.find({ id: report['id'] })
.count(Report_find_count_callback); // --> take out
};
res.json({
message: 'Grabbed Report'
});
}

function Report_find_count_callback(err, count) { // <-- define here
...
if (count == 0) {
report.save(function(err) { // !! report is undefined here
console.log('saved');
if (err)
res.send(err); // !! res is undefined here
});
}
}

需要注意的是,您将无法访问以前的回调中的所有变量,因为你已经把它们排除在范围之外了。

这可以通过某种“依赖注入(inject)”包装来传递所需的变量来解决。

router.route('/report') // the REST api address
.post(calling_a_POST)

function calling_a_POST(req, res) {
...
var data = "";
https.get(url, function callback(response) {
...
response.on("end", function(err, data){ // take these arguments
response_on_end(err, data, res); // plus the needed variables
});
response.on("error", console.error);
});
}

function response_on_end(err, data, res) { // and pass them to function defined outside
...
for (var i = 0; i < length; i++) {
var report = new Report(array.pop());
...
Report.find({ id: report['id'] })
.count(function(err, count){
Report_find_count(err, count, report, res); // same here
});
};
res.json({ // res is now available
message: 'Grabbed Report'
});
}

function Report_find_count(err, count, report, res) { // same here
...
if (count == 0) {
report.save(function(err) { // report is now available
console.log('saved');
if (err)
res.send(err); // res is now available
});
}
}
<小时/>

When I execute the response_on_end function, I am getting the undefined:1 unexpected token u error. I am pretty much sure it has something to do with this line: var jsonData = JSON.parse(data) My response_on_end is as below: var jsonData = JSON.parse(data); // problem here

我意识到我在这里犯了一个错误:

function calling_a_POST(req, res) {
...
var data = "";
https.get(url, function callback(response) {
...
//sponse.on("end", function(err, data){
response.on("end", function(err){ // data shouldn't be here
response_on_end(err, data, res);
});
response.on("error", console.error);
});
}

我可以预见的另一个问题,实际上可能不会出现在这里,但无论如何还是最好谈论一下。data 变量,因为它是一个字符串,是与对象不同的原始类型,所以它是“按值传递”。 More info

最好将变量包装在对象中并传递该对象,因为 javascript 中的对象始终是“通过引用传递”。

function calling_a_POST(req, res) {
...
// var data = ""; //
var data_wrapper = {};
data_wrapper.data = {}; // wrap it in an object
https.get(url, function callback(response) {
...
response.on("data", function(chunk){
data_wrapper.data += chunk.toString() + ""; // use the dot notation to reference
});
response.on("end", function(err){
response_on_end(err, data_wrapper, res); // and pass that object
});
response.on("error", console.error);
});
}

function response_on_end_callback(err, data_wrapper, res) {
var data = data_wrapper.data; // later redefine the variable
...
for (var i = 0; i < length; i++) {
var report = new Report(array.pop());
...

关于node.js - 如何处理 for 循环中的回调(Node.JS),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29343116/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com