如何在for循环中处理回调(Node.JS)

我试图用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. console.log(report)=将在Mongo内部存储的数据

  6. 数字3-7重复100次,因为长度等于100
  7. console.log(count)= 0或1
  8. 数字9重复100次
  9. console.log(’保存’)
  10. 数字11重复100次
  11. 最后,仅100个数据中的最后一个存储到Mongo中

我需要的是某种技术或方法来处理这些回调,它们在一个接一个地执行,而不是在循环之后顺序执行。我可以肯定这是问题所在,因为我的其他REST

API都可以正常工作。

我研究了异步方法,promise,递归函数以及其他一些我无法理解如何解决此问题的方法。我真的希望有人能对此事有所启发。

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

回答:

这个问题被称为“回调地狱”。还有很多其他方法,例如使用Promise和Async库。

我对本机asyncES7所带来的一切感到更加兴奋,您实际上可以立即使用Transpiler库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

});

}

}

需要注意的是,您将无法访问以前用作回调的所有变量,因为您已将它们移出了范围。

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

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

});

}

}


当我执行response_on_end函数时,undefined:1 unexpected token

u出现错误。我非常确定这与以下行有关:var jsonData = JSON.parse(data)

response_on_end的如下: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变量,因为它是一个字符串,它是不同于对象的原语类型,它是“按值传递”。

更多信息

最好将变量包装在一个对象中并传递该对象,因为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());

...

以上是 如何在for循环中处理回调(Node.JS) 的全部内容, 来源链接: utcz.com/qa/424926.html

回到顶部