Array not reseting in Node.js

依然范特西╮ 提交于 2021-01-28 08:09:53

问题


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.

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.

Here is my code:

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)
    });
};

回答1:


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.

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);
    }));
}

But, I presume you need to change all your mysql programming over to the mysql2 promises interface.

There are also promise wrappers for the original mysql library such as https://www.npmjs.com/package/mysql-promise.


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.

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());
                }
            });
        })
    });
};



回答2:


Just put allPosts in new Promise block.



来源:https://stackoverflow.com/questions/57701211/array-not-reseting-in-node-js

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!