Node.js Async | 从api插入postgresql数据库结果

我是node.js的新手。 我想实现的是以下几点:

  1. 连接到我的postgresql数据库,并获得一个地方(id,坐标)的信息。
  2. 调用天气api并使用上一步获得的坐标获取该点的信息。
  3. 将返回的json插入到数据库中。 我得到8小时的对象,每3小时的天气信息(0,3,6,9,12,15,18,21)。 我需要遍历这些对象,并将它们存储在数据库中的8条logging中。

我写了下面的代码:

app.get('/getapi', function(req, res){ var json_bbdd; //------------ BBDD CONNECTION---------------- var pg = require('pg'); var conString = "postgres://postgres:postgres2@localhost/places"; var client = new pg.Client(conString); client.connect(function(err) { if(err) { console.log('could not connect to postgres'); } client.query('SELECT * from places where id=3276', function(err, result) { if(err) { console.log('error running query'); } json_bbdd=result.rows[0]; var coords = JSON.parse(json_bbdd.json).coordinates; var id = json_bbdd.id; var input = { query: coords[1] + ',' + coords[0] , format: 'JSON', fx: '', callback: 'MarineWeatherCallback' }; var url = _PremiumApiBaseURL + "marine.ashx?q=" + input.query + "&format=" + input.format + "&fx=" + input.fx + "&key=" + _PremiumApiKey + "&tide=yes"; $.ajax({ type: 'GET', url: url, async: false, contentType: "application/json", dataType: 'jsonp', success: function (json) { var date= json.data.weather[0].date; for (var i=0; i < 8; i++){ var hourly = json.data.weather[0].hourly[i]; var time= hourly.time; client.query('INSERT into parte (id, date, time) VALUES($1, $2, $3)', [id, date, time], function(err, result) { if (err) { console.log(err); } else { console.log('row inserted: ' + id + ' ' + time); } }); } // FOR }, error: function (e) { console.log(e.message); } }); client.end(); }); }); }); 

步骤1和2完美地执行。 另一方面,第三步什么都不做,甚至不会抛出错误。

我读了这篇文章: node-postgres不会插入数据,但不会抛出错误使用asynchronous模块可以帮助,但我不知道如何重写代码。 我需要一些帮助。

问候,Aitor

我没有testing你的代码片段,只能帮你处理看起来不好的事情。

  1. 最好不要在节点服务器上使用jQuery。 有称为request优秀库做远程http请求。
  2. 你应该更好地处理数据库错误,因为在你的例子中你的代码会在DB错误后继续。
  3. 您正在调用client.end()过早,当您尝试向数据库插入数据时,连接已经closures。 你必须在成功和错误函数结束时移动client.end() ,并等待所有的callback完成。
  4. 我认为使用连接池而不是Client更好。
  5. 您可以在PostgreSQL使用JSONtypes来避免序列化/反序列化代码中的JSON数据。

这里是修改的例子(未经testing)。 我没有在这里replacejQuery,包括一些小调整。

 var pg = require('pg'); var conString = "postgres://postgres:postgres2@localhost/places"; app.get('/getapi', function(req, res, next){ var json_bbdd; //------------ BBDD CONNECTION---------------- pg.connect(conString, function(err, client, done) { if(err) { // example how can you handle errors console.error('could not connect to postgres'); return next(new Error('Database error')); } client.query('SELECT * from places where id=3276', function(err, result) { if(err) { console.error('error running query'); done(); return next(new Error('Database error')); } json_bbdd = result.rows[0]; var coords = JSON.parse(json_bbdd.json).coordinates; var id = json_bbdd.id; var input = { query: coords[1] + ',' + coords[0] , format: 'JSON', fx: '', callback: 'MarineWeatherCallback' }; var url = _PremiumApiBaseURL + "marine.ashx?q=" + input.query + "&format=" + input.format + "&fx=" + input.fx + "&key=" + _PremiumApiKey + "&tide=yes"; $.ajax({ type: 'GET', url: url, async: false, contentType: "application/json", dataType: 'jsonp', success: function (json) { var date = json.data.weather[0].date; var callbacks = 0; for (var i=0; i < 8; i++) { var hourly = json.data.weather[0].hourly[i]; var time= hourly.time; client.query( 'INSERT into parte (id, date, time) VALUES($1, $2, $3)', [id, date, time], function(err, result) { if (err) { console.log(err); } else { console.log('row inserted: ' + id + ' ' + time); } callbacks++; if (callbacks === 8) { console.log('All callbacks done!'); done(); // done(); is rough equivalent of client.end(); } }); } // FOR }, error: function (e) { console.error(e.message); done(); // done(); is rough equivalent of client.end(); return next(new Error('Http error')); } }); }); }); }); 

好吧,现在又迎来了另外一个问题……我怀疑是不是创build了一个新post,但是我认为这可能和以前的post有关系。

目的是从数据库中读取而不是从一个地方读取3个地方,并且对每个地方执行与之前相同的处理。 代码如下(ivoszz提出的更改):

 app.get('/getapi', function(req, res, next){ //------------ BBDD CONNECTION---------------- pg.connect(conString, function(err, client, done) { if(err) { // example how can you handle errors console.error('could not connect to postgres',err); return next(new Error('Database error')); } client.query('SELECT * from places where id>3274 and id<3278', function(err, result) { if(err) { console.error('error running query',err); done(); return next(new Error('Database error')); } var first_callback = 0; for (var y=0; y<result.rows.length; y++) { var coords = JSON.parse(result.rows[y].json).coordinates; var id = result.rows[y].id; var input = { query: coords[1] + ',' + coords[0] , format: 'JSON', fx: '' }; var url = _PremiumApiBaseURL + "marine.ashx?q=" + input.query + "&format=" + input.format + "&fx=" + input.fx + "&key=" + _PremiumApiKey; request(url, function(err, resp, body) { body = JSON.parse(body); if (!err && resp.statusCode == 200) { var date = body.data.weather[0].date; var callbacks = 0; for (var i=0; i < 8; i++) { var hourly = body.data.weather[0].hourly[i]; client.query( 'INSERT into parte (id, date, time) VALUES($1, $2, $3)', [id, date, hourly.time], function(err, result) { if (err) { console.log(err); } else { console.log('row inserted: ' + id + ' iteration ' + i); } callbacks++; if (callbacks === 8) { console.log('All callbacks done!from id '+id); //done(); // done(); is rough equivalent of client.end(); //res.send("done"); } }); } // FOR } else { // if the API http request throws an error console.error(err); done(); // done(); is rough equivalent of client.end(); return next(new Error('Http API error')); } }); // REQUEST API URL first_callback++; if (first_callback === result.rows.length-1) { console.log('All global callbacks done!'); done(); // done(); is rough equivalent of client.end(); res.send("done"); }} }); // SELECT from pg }); // CONNECT to pg }); // app.get 

我不知道为什么它试图插入id = 3277三次,而不是插入id = 3275,id = 3276,然后id = 3277 …它是这样做的:它插入的第一个8logging第一次(id = 3277),但它会引发一个错误,说明logging已被插入(主键= id,date,时间)与ID 3277 …

看起来,首先做了第一个FOR的3次迭代,然后做了第二个FOR的3次迭代,但是使用了最后一次迭代(place)的信息。 我无法理解