Javascript 执行多个查询后终止mysql连接
我有一些node.js代码,它在循环中从API获取数据,并运行多个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
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
和我编写的函数,您可以做到仅在使用本机模块(无论是否使用浏览器)的并行执行中使用相同的方法。