阵列未在Node.js中重置
我正在运行一个运行良好的Node + Express API,我唯一的问题是返回复杂查询作为响应时,我将响应设置为的变量在两次请求之间未重置
I am running a Node+Express API that is working quite well, the only problem I have is when returning a complex query as a response, the variable to which I set the response to is not getting reset between requests.
它会重复发送给客户的回复,例如回复1、2、3,然后下一个回复会回复1、2、3、1、2、3.因此,基本上,它是连接数据,而不是设置 allPosts
变量再次为空.
It duplicates replies to the client such as replying 1, 2, 3 then the next reply replies 1, 2, 3, 1, 2, 3. So basically, it's concatenating data and not setting the allPosts
variable to null again.
这是我的代码:
var allPosts = [];
chirprdb.allPosts = (userData) => {
return new Promise((resolve, reject) => {
userData.locations.forEach((location) =>{
pool.query('SELECT posts.post_id, posts.title, posts.description FROM posts_locations INNER JOIN posts on posts.post_id = posts_locations.post_id WHERE posts_locations.location_id = ?', location.location_id, (err, results) => {
if(err){
return reject(err);
}
// allPosts.push(results)
results.forEach((result) =>{
allPosts.push(result)
})
});
})
resolve(allPosts)
});
};
进行此类编程的最佳方法是在数据库上使用Promise接口,然后可以使用基于Promise的工具来管理异步操作.
The best way to program something like this is to use a promise interface on your database and then you can use promise-based tools for managing asynchronous operations.
mysql2模块具有一个Promise接口(它代替了回调接口),而您拥有的该函数将如下所示:
The mysql2 module has a promise interface (that replaces the callback interface) and this function you have would look something like this:
const mysql = require('mysql2/promise');
// returns a promise that resolves with a
chirprdb.allPosts = (userData) => {
return Promise.all(usrData.locations.map(location => {
return pool.query('SELECT posts.post_id, posts.title, posts.description FROM posts_locations INNER JOIN posts on posts.post_id = posts_locations.post_id WHERE posts_locations.location_id = ?', location.location_id);
}));
}
但是,我想您需要将所有mysql编程更改为mysql2 promises接口.
But, I presume you need to change all your mysql programming over to the mysql2 promises interface.
对于原始mysql库,也有Promise包装器,例如 https://www.npmjs.com/package/mysql-promise .
There are also promise wrappers for the original mysql library such as https://www.npmjs.com/package/mysql-promise.
您的方案不起作用,因为您正在调用 resolve(allPosts)
之前,已将任何内容添加到 allPosts
中,因此您可能会在其仍处于静止状态时再次调用它在 allPosts
中添加更多内容,因此您感觉它不为空.无论如何,您当前的方法是一个计时灾难.
Your scheme does not work because you're calling resolve(allPosts)
BEFORE anything has been added to allPosts
and thus you're probably calling it again while it's still adding more things to allPosts
and thus you feel like it isn't empty. In any case, your current method is a timing disaster.
如果要保留mysql的回调接口,则必须实现某种计数器,该计数器告诉您何时完成所有请求,如下所示:
If you want to keep with the callback interface for mysql, then you have to implement some sort of counter that tells you when all your requests are done like this:
chirprdb.allPosts = (userData) => {
let allPosts = [];
let cntr = 0;
return new Promise((resolve, reject) => {
for (let i = 0; i < userData.locations.length; i++) {
let location = userData.locations[i];
pool.query('SELECT posts.post_id, posts.title, posts.description FROM posts_locations INNER JOIN posts on posts.post_id = posts_locations.post_id WHERE posts_locations.location_id = ?', location.location_id, (err, results) => {
if(err){
return reject(err);
}
++cntr;
allPosts[i] = results;
// if all queries done now
if (cntr === userData.locations.length) {
resolve(allPosts.flat());
}
});
})
});
};