Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/446.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/bash/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript Node.js同步循环或迭代异步语句_Javascript_Mysql_Node.js_Synchronous - Fatal编程技术网

Javascript Node.js同步循环或迭代异步语句

Javascript Node.js同步循环或迭代异步语句,javascript,mysql,node.js,synchronous,Javascript,Mysql,Node.js,Synchronous,我想为每个循环做一个测试,但是让它同步运行。循环的每个迭代都将执行一个http.get调用,该调用将返回json,以便将值插入数据库。问题是for循环是异步运行的,这会导致所有http.get同时运行,并且我的数据库不会插入所有数据。我使用async foreach尝试执行我希望它执行的操作,但如果我能够正确执行,我不必使用它 mCardImport = require('m_cardImport.js'); var http = require('http'); app.get('/path/

我想为每个循环做一个测试,但是让它同步运行。循环的每个迭代都将执行一个http.get调用,该调用将返回json,以便将值插入数据库。问题是for循环是异步运行的,这会导致所有http.get同时运行,并且我的数据库不会插入所有数据。我使用async foreach尝试执行我希望它执行的操作,但如果我能够正确执行,我不必使用它

mCardImport = require('m_cardImport.js');
var http = require('http');
app.get('/path/hi', function(req, res) {

mCardImport.getList(function(sets) {
  forEach(sets, function(item, index, arr) {
    theUrl = 'http://' + sets.set_code + '.json';
    http.get(theUrl, function(res) {

      var jsonData = '';
      res.on('data', function(chunk) {
        jsonData += chunk;
      });

      res.on('end', function() {
        var theResponse = JSON.parse(jsonData);
        mCardImport.importResponse(theResponse.list, theResponse.code, function(theSet) {
          console.log("SET: " + theSet);
        });
      });
    });
  });
});
});
还有我的模特

exports.importResponse = function(cardList, setCode, callback) {

mysqlLib.getConnection(function(err, connection) {

forEach(cardList, function(item, index, arr) {

  var theSql = "INSERT INTO table (name, code, multid, collector_set_num) VALUES "
   + "(?, ?, ?, ?) ON DUPLICATE KEY UPDATE id=id";
  connection.query(theSql, [item.name, setCode, item.multid, item.number], function(err, results) {
    if (err) {
      console.log(err);
    };
  });
});
});
callback(setCode);
};

要循环并同步链接异步操作,最干净的解决方案可能是使用承诺库(承诺是在ES6中引入的,这是一种方法)

使用,这可能是

Var p = Promise.resolve();
forEach(sets, function(item, index, arr) {
    p.then(new Promise(function(resolve, reject) {
         http.get(theUrl, function(res) {
         ....
         res.on('end', function() {
              ...
              resolve();
         }
    }));
});
p.then(function(){
   // all tasks launched in the loop are finished
});

使用递归,代码非常干净。等待http响应返回,然后触发下一次尝试。这将适用于所有版本的节点

var urls = ['http://stackoverflow.com/', 'http://security.stackexchange.com/', 'http://unix.stackexchange.com/'];

var processItems = function(x){
  if( x < urls.length ) {
    http.get(urls[x], function(res) {

      // add some code here to process the response

      processItems(x+1);
    });
  }
};

processItems(0);

注意:这两个示例都跳过了错误处理,但您可能应该在生产应用程序中使用错误处理。

我发现在每次调用完成后,我没有释放mysql连接,这会导致连接阻塞,导致连接失败,并且似乎是同步问题

显式调用
connection.release()后它使我的代码即使以异步方式也能100%正确工作

感谢大家发布此问题。

“严格使用”;
"use strict";

var Promise = require("bluebird");
var some = require('promise-sequence/lib/some');

var pinger = function(wht) {
    return new Promise(function(resolve, reject) {
        setTimeout(function () { 

            console.log('I`ll Be Waiting: ' + wht);
            resolve(wht);

        }, Math.random() * (2000 - 1500) + 1500);
    });
}

var result = [];
for (var i = 0; i <= 12; i++) {
    result.push(i);
}

some(result, pinger).then(function(result){
  console.log(result);
});
var承诺=要求(“蓝鸟”); var some=require('promise-sequence/lib/some'); var pinger=功能(wht){ 返回新承诺(功能(解决、拒绝){ setTimeout(函数(){ log('我将等待:'+wht); 解决(wht); },Math.random()*(2000-1500)+1500); }); } var结果=[]; 对于(var i=0;i
var url=['http://stackoverflow.com/', 'http://security.stackexchange.com/', 'http://unix.stackexchange.com/'];
对于(i=0;i
只需将循环包装在一个
异步
函数中即可。此示例说明了我的意思:

const oneSecond = async () => 
    new Promise((res, _) => setTimeout(res, 1000));
此函数仅在1秒后完成:

const syncFun = () => {
    for (let i = 0; i < 5; i++) {
        oneSecond().then(() => console.log(`${i}`));
    }
}

syncFun(); // Completes after 1 second ❌
const syncFun=()=>{
for(设i=0;i<5;i++){
oneSecond().then(()=>console.log(`${i}`));
}
}
syncFun();//1秒后完成❌
这一个按预期工作,5秒后完成:

const asyncFun = async () => {
    for (let i = 0; i < 5; i++) {
        await oneSecond();
        console.log(`${i}`);
    }
}

asyncFun(); // Completes after 5 seconds ✅
constasyncfun=async()=>{
for(设i=0;i<5;i++){
等待一秒钟();
log(`${i}`);
}
}
asyncFun();//5秒后完成✅

您可以使用
async。虽然每个
都有您发布的内容,但您应该能够并行执行此异步/操作,因此我将尝试找出为什么您的所有数据都没有插入。没有理由无缘无故地减慢速度。我也不确定为什么。但我预计会有24000条记录,而且它的作用会小得多。这是ike 3000或5000当我截短表并重新运行它时,数字并不总是相同的。所以我认为我在太短的时间内抛出了太多http.get请求和/或太多MYSQL调用,导致遗漏/删除了一些内容。@Joe我想感谢你建议我重新查看我的代码,但我发现我没有在每个exports.importResponse()的末尾显式调用connection.release()。我认为connection.release()是自动调用的,但当我再次检查并显式添加它时,它现在工作了,所有24000条记录都按预期添加。再次感谢!因此循环迭代开始,传递到p。然后,循环暂停,一旦p。然后返回下一个循环迭代开始?我理解正确吗?不完全正确:循环本身不会暂停。但是然后使用传递的回调只会一个接一个地调用(设i=0;注意JavaScript不提供尾部递归,并且递归函数只能在递归深度有硬限制的情况下使用。如果你不知道这意味着什么,并且你知道你会有很多循环,那么就用承诺:)这真是一个很好的答案。我正在研究如何使for循环同步。它工作起来很有魅力:)是否需要
var i=0;
?@betweenbrain哈哈,好主意。我很惊讶直到现在还没有人注意到。修复了。这可能会在较大的数据集上出现问题,因为一旦迭代完成,内存就不会被释放complete@HarshaGoli我同意,但这是一个合理的起点。如果需要大规模,递归总是在进行除非仔细优化,否则可能会出现内存问题。您应该在代码中添加一些解释,以便其他人可以从中学习。由于for循环将在异步http.get调用之前完成,因此这不会像预期的那样工作。此外,这种方式也不能保证操作顺序。如果stackoverflow有一天很慢,它可能会返回其结果位于所有其他URL之后。
const syncFun = () => {
    for (let i = 0; i < 5; i++) {
        oneSecond().then(() => console.log(`${i}`));
    }
}

syncFun(); // Completes after 1 second ❌
const asyncFun = async () => {
    for (let i = 0; i < 5; i++) {
        await oneSecond();
        console.log(`${i}`);
    }
}

asyncFun(); // Completes after 5 seconds ✅