Javascript 执行多个查询后终止mysql连接

Javascript 执行多个查询后终止mysql连接,javascript,mysql,node.js,asynchronous,Javascript,Mysql,Node.js,Asynchronous,我有一些node.js代码,它在循环中从API获取数据,并运行多个mysql查询来更新一些行 我遇到的问题是,在我使用connection.end()终止mysql连接之前,脚本一直在运行。我是异步代码的新手。我在哪里调用终止函数,以便在所有查询执行完毕时执行它?这种设计的正确模式是什么?有什么好处吗 这是我目前拥有的代码片段(为了简单起见,删除了错误处理): var connection=mysql.createConnection({host,user,etc..}); 对于(变量i=0;i

我有一些node.js代码,它在循环中从API获取数据,并运行多个mysql查询来更新一些行

我遇到的问题是,在我使用
connection.end()
终止mysql连接之前,脚本一直在运行。我是异步代码的新手。我在哪里调用终止函数,以便在所有查询执行完毕时执行它?这种设计的正确模式是什么?有什么好处吗

这是我目前拥有的代码片段(为了简单起见,删除了错误处理):

var connection=mysql.createConnection({host,user,etc..});
对于(变量i=0;i<10;i++){
变量url=”http://api.com?i=“+i;
请求(url、函数(错误、响应、正文){
var data=JSON.parse(body);
用于(数据中的el){
connection.query(
“更新表集列=?其中符号=?”,
[
数据[el].col,
埃尔
]
);
}
});
}
//这将在执行所有查询之前运行
//导致错误的
连接。结束();

因此,这里的问题是,您正在以同步方式在这里的数据中循环:

var data = JSON.parse(body);
for (el in data) {
    connection.query(
         "UPDATE table SET col = ? WHERE symbol = ?",
         [
             data[el].col,
             el
         ]
     );
 }
mysql
模块以回调方式处理查询:

connection.query(query, function(error, rows, fields) {
    if (error) {
       return callback(error);
    } else {
       return callback(null,rows);
    }
});
其中,
callback
具有签名
callback(error,rows)
,因此您可以通过这种方式处理结果,该方式假定具有可重用的函数:

  var executeQuery = function(query,callback) {
        var self=this;
        this.connection.query(query, function(error, rows, fields) {
            if (error) {
                return callback(error);
            } else {
                return callback(null,rows);
            }
        });
    }
var promiseAllP = function(items, block) {
        var promises = [];
        items.forEach(function(item,index) {
          promises.push( function(item,i) {
              return new Promise(function(resolve, reject) {
                return block.apply(this,[item,index,resolve,reject]);
              });
            }(item,index))
        });
        return Promise.all(promises);
      }
你可以像这样调用你的代码

executeQuery(statement, function(error,rows) {
  //...
})

这样说,你必须考虑你正在对数据库进行多个查询,不建议在for循环中这样做。你应该考虑使用一个更好的解决方案,它可以是一个瀑布,正如你所说的或一个承诺,都使用承诺范式。

假设要拥有这个漂亮的函数:

  var executeQuery = function(query,callback) {
        var self=this;
        this.connection.query(query, function(error, rows, fields) {
            if (error) {
                return callback(error);
            } else {
                return callback(null,rows);
            }
        });
    }
var promiseAllP = function(items, block) {
        var promises = [];
        items.forEach(function(item,index) {
          promises.push( function(item,i) {
              return new Promise(function(resolve, reject) {
                return block.apply(this,[item,index,resolve,reject]);
              });
            }(item,index))
        });
        return Promise.all(promises);
      }
它将一个项目数组和一个执行函数作为输入,执行函数是
函数(项目、索引、解析、拒绝)
,具有承诺的解析和拒绝函数,因此让我们在承诺中也使用
executeQuery
函数:

var executeQueryP = function(query) {
        var self=this;
        return new Promise(function(resolve, reject) {
           self.connection.query(query, function(error, rows, fields) {
            if (error) {
                return reject(error);
            } else {
                return resolve(null,rows);
            }
        });
    }
现在,您可以以完全异步的方式处理数据:

promiseAllP(data,(item,index,resolve,reject) => {
    var query= "UPDATE table SET col = %s WHERE symbol = %s";
    // example: prepare the query from item in the data
    query = replaceInString(query,item.col,item);
    executeQueryP(query)
    .then(result => resolve(result))
    .catch(error => reject(error))    
})
.then(results => { // all execution completed
 console.log(results)
})
.catch(error => { // some error occurred while executing
  console.error(error)
})
其中,
replaceInString
将帮助您准备对账单

   var replaceInString = function() {
    var args = Array.prototype.slice.call(arguments);
    var rep= args.slice(1, args.length);
    var i=0;
    var output = args[0].replace(/%s|%d|%f|%@/g, function(match,idx) {
      var subst=rep.slice(i, ++i);
      return( subst );
    });
     return(output);
  },//replace,
这就是我们在这里所做的:

  • 仅用于本地承诺
  • 将您的mysql查询转化为承诺
  • 以完全异步的方式对数据调用语句
  • 使用Promise和Promise all范例,该范例允许您收集Promise的结果,并在所有函数完成后返回调用方
  • 捕获所有语句执行中的错误
  • 添加了一种使用参数实现语句的简单方法

还请注意箭头函数语法
(param1,param2)=>
,它简化了编写函数的方式,这对Promise范例有很大帮助。

对于任何感兴趣的人,我最终通过混合使用Promission和计算查询来解决它,这与本文的思路类似(不确定此代码是否实际有效,但想法确实存在):

函数fetchFromAPI(){ 返回新承诺((解决、拒绝)=>{ var url=[]; 对于(变量i=0;i<10;i++){ URL.push(“http://api.com?i=“+i); } var数据=[]; var requestedUrls=0; forEach(url=>{ 请求(url,(错误、响应、正文){ 如果(错误)拒绝(错误); data.push(JSON.parse(body)); requestedUrls++; if(requestedUrls==url.length)解析(数据); }; }); } } fetchFromAPI()。然后(数据=>{ createConnection({user、hostname等..}); var processedKeys=0; data.forEach(el=>{ query(“更新表集名称=?其中id=?”,[el.name,el.id],(err,rows,fields)=>{ processedKeys++; if(processedKeys==data.length){ 连接。结束(); } }); } }).catch(错误=>{ 控制台错误(err); });
这非常有帮助,谢谢。那么使用async.parallel如何?这是否也适用于此目的?有几种框架可以帮助您,但由于您处于第一阶段,我强烈建议您了解这里发生的事情,因此使用本机的
Promise
和我编写的函数,您可以做到仅在使用本机模块(无论是否使用浏览器)的并行执行中使用相同的方法。