节点在插入之前关闭数据库连接或者根本不关闭数据库连接

时间:2017-12-20 04:14:12

标签: node.js asynchronous

我有以下代码执行以下操作:

  • 打开数据库连接(使用pg)。
  • 致电Twitter Trends API(不同地点一次或多次)。
  • 浏览趋势项并将每个项存储到数据库中。
  • 关闭数据库连接。

我尝试了一个直接的代码。我首先遇到了以下错误。

Error: Connection terminated by user

这是代码。

client.connect();

const text = 'INSERT INTO TRENDS(AS_OF, location_name, name, tweet_volume, rank) VALUES($1, $2, $3, $4, $5) RETURNING *';

T.get('trends/place', { id: 2295424 }, function(err, data, response) {
    data_json = data[0];
    var rankNum = 0;
    console.log(data_json.locations[0].name);
    for (var item of data_json.trends) {
        rankNum++;
        var values = [data_json.as_of, data_json.locations[0].name, item.name, item.tweet_volume, rankNum];
        client.query(text, values)
            .then(res => {
                console.log(res.rows[0])
            })
            .catch(e => console.error(e.stack));
    };
    client.end();
});

看来,数据库连接(client.end())在client.query()运行之前被调用并关闭。所以,我重写了我的代码,等待client.query完成,然后使用async / await调用client.end。

client.connect();

const text = 'INSERT INTO TRENDS(AS_OF, location_name, name, tweet_volume, rank) VALUES($1, $2, $3, $4, $5) RETURNING *';

T.get('trends/place', { id: 23424848 }, function (err, data, response) {
    data_json = data[0];
    var rankNum = 0;
    console.log(data_json.locations[0].name);

    function insRows(){
    return new Promise( resolve => {
        for (var item of data_json.trends) {
        rankNum++;
        var values = [data_json.as_of, data_json.locations[0].name, item.name, item.tweet_volume, rankNum];
        client.query(text, values)
            .then(res => {
                console.log(res.rows[0])
            })
            .catch(e => console.error(e.stack));
        };
    });
    };

    async function closeDBConnection(){
        const a = await insRows();
        client.end();
        return 0;
    };

    closeDBConnection().then( v => {
         console.log(v);
    });
});

这个带有async / await的代码运行正常,但是数据库连接没有关闭,节点只是挂起来转到CTRL + C.

  • 节点版本:v9.2.1
  • 我使用命令运行程序:node app.js

更新1

使用Promise数组和async / await更新代码。这不起作用:

client.connect();

const text = 'INSERT INTO TRENDS(AS_OF, location_name, name, tweet_volume, rank) VALUES($1, $2, $3, $4, $5) RETURNING *';
T.get('trends/place', { id: 23424848 }, function(err, data, response) {
    const data_json = data[0];
    let rankNum = 0;
    const queryPromises = [];
    console.log(data_json.locations[0].name);
    async function insRows() {
        for (let item of data_json.trends) {
            rankNum++;
            const values = [data_json.as_of, data_json.locations[0].name, item.name, item.tweet_volume, rankNum];
            queryPromises.push(client.query(text, values)
                .then(res => console.log(res.rows[0]))
                .catch(e => console.error(e.stack)));
        };
    };

    (async = () => {
        await Promise.all(queryPromises);
        client.end();
    });
});

我也尝试过:

    async function insRows(){
     /* same as above*/
    }
    await Promise.all(queryPromises);
    client.end();

我收到以下错误(node app_ans.js):

        await Promise.all(queryPromises);
        ^^^^^

SyntaxError: await is only valid in async function

2 个答案:

答案 0 :(得分:1)

您的代码永远不会调用您创建的承诺的resolve,但您不需要创建自己的承诺,因为client.query已经返回了承诺。我会这样写:

const data_json = data[0];
let rankNum = 0;
const queryPromises = [];

for (let item of data_json.trends) {
    rankNum++;
    const values = [data_json.as_of, data_json.locations[0].name, item.name, item.tweet_volume, rankNum];
    queryPromises.push(client.query(text, values)
        .then(res => console.log(res.rows[0]))
        .catch(e => console.error(e.stack)));
};
await Promise.all(queryPromises);
client.end();

答案 1 :(得分:1)

首先,我假设您使用 npm-request 包将GET请求发送到Twitter trends/places api,如果是,我建议使用请求承诺 ;这允许我们直接使用Async / Await,因为它支持Promises而不是回调。话虽如此,问题可能在于您构建GET请求的方式。使用T.get('trends/place?id=23424848'代替T.get('trends/place', { id: 23424848 }

您也可以考虑以下代码:

const T = require('request-promise')
const { Client } = require('pg')
const client = new Client()

await client.connect()

const getTrendsAndUpdate = async (id) => {
    const text = 'INSERT INTO TRENDS(AS_OF, location_name, name, tweet_volume, rank) VALUES($1, $2, $3, $4, $5) RETURNING *';

    const closeDBConnection = async () => {
        await client.end();
        console.log('DB Connection closed')
        return 0;
    }

    try{
        const data_json = await T.get('trends/place?id='+id, {json:true});
        let trends = data_json['trends'];
        let as_of = data_json['as_of'];
        let location_name = data_json['locations']['name'];
        let rankNum = 0;
        let a = await trends.forEach(async item => {
            rankNum++;
            let values = [data_json.as_of, data_json.locations[0].name, item.name, item.tweet_volume, rankNum];
            let res = await client.query(text, values)
            console.log(res.rows[0])
        });
        if(a){
            await closeDBConnection()
            return
        }
    } catch(e){ console.error(e.stack) }
}

getTrendsAndUpdate(23424848)

希望这可以解决问题并指出正确的方向。