编辑:我使用的是节点v8.0.0
我刚刚开始学习如何使用node-postgres访问SQL数据库,并且我在访问多个数据库以便以可工作的格式收集数据方面遇到一些麻烦,特别是在forEach循环中执行多个查询时。经过几次尝试后,我尝试了async / await,但是我收到了以下错误:
await client.connect()
^^^^^^
SyntaxError: Unexpected identifier
当我尝试使用游泳池或按顺序调用.query时,我会得到类似
的内容1
[]
could not connect to postgres Error: Connection terminated
以下是我的代码的缩写版本:
const { Client } = require('pg');
const moment = require('moment');
const _ = require('lodash');
const turf = require('@turf/turf');
const connString = // connection string
var collected = []
const CID = 300
const snaptimes = // array of times
var counter=0;
const client = new Client(connString);
function createArray(i,j) {
// return array of i arrays of length j
}
await client.connect()
snaptimes.forEach(function(snaptime){
var info = {}; // an object of objects
// get information at given snaptime from database 1
const query1 = // parametrized query selecting two columns from database 1
const result1 = await client.query(query1, [CID,snaptime]);
var x = result1.rows;
for (var i = 0; i < x.length; i++) {
// store data from database 1 into info
// each row is an object with two fields
}
// line up subjects on the hole
const query2 = // parametrized query grabbing JSON string from database 2
const result2 = await client.query(query2, [CID,snaptime]);
const raw = result2.rows[0].JSON_col;
const line = createArray(19,0); // an array of 19 empty arrays
for (var i = 0; i < raw.length; i++) {
// parse JSON object and record data into line
}
// begin to collect data
var n = 0;
var g = 0;
// walk down the line
for (var i = 18; i > 0; i--) {
// if no subjects are found at spot i, do nothing, except maybe update g
if ((line[i] === undefined || line[i].length == 0) && g == 0){
g = i;
} else if (line[i] !== undefined && line[i].length != 0) {
// collect data for each subject if subjects are found
line[i].forEach(function(subject){
const query 3 = // parametrized query grabbing data for each subject
const result3 = await client.query(query3,[CID,subject,snaptime]);
x = result3.rows;
const y = moment(x[0].end_time).diff(moment(snaptime),'minutes');
var yhat = 0;
// the summation over info depends on g
if (g===0){
for (var j = i; j <= 18; j++){
yhat = moment.duration(info[j].field1).add(yhat,'m').asMinutes();
}
} else {
for (var j = i; j <= 18; j++){
if (i<j && j<g+1) {
yhat = moment.duration(info[j].field2).add(yhat,'m').asMinutes();
} else {
yhat = moment.duration(info[j].field1).add(yhat,'m').asMinutes();
}
}
}
collected.push([y,yhat,n,i]);
});
}
n+=line[i].length;
g=0;
}
// really rough work-around I once used for printing results after a forEach of queries
counter++;
if (counter===snaptimes.length){
console.log(counter);
console.log(collected);
client.end();
}
});
答案 0 :(得分:1)
问题是由于您的forEach回调不是async
:
snaptimes.forEach(function(snaptime){
应该是:
snaptimes.forEach(async function (snaptime) {
让await
可以识别。
请记住,async
函数会立即返回,并返回一个承诺,该承诺最终由return
函数的async
语句解析(或者在async
函数中引发的未捕获异常被拒绝{1}}功能)。
但请确保您的Node版支持async
/ await
:
--harmony
标志一起使用。--harmony
标志。请参阅:http://node.green/#ES2017-features-async-functions
另请注意,您可以在使用await
关键字声明的函数内使用async
。如果要在脚本或模块的顶层使用它,则需要将其包装在一个立即调用的函数表达式中:
// cannot use await here
(async () => {
// can use await here
})();
// cannot use await here
示例:
const f = () => new Promise(r => setTimeout(() => r('x'), 500));
let x = await f();
console.log(x);
打印:
$ node t1.js
/home/rsp/node/test/prom-async/t1.js:3
let x = await f();
^
SyntaxError: Unexpected identifier
但是这个:
const f = () => new Promise(r => setTimeout(() => r('x'), 500));
(async () => {
let x = await f();
console.log(x);
})();
打印:
$ node t2.js
x
延迟0.5秒后,正如预期的那样。
在不支持async
/ await
的节点版本上,将打印第一个(不正确的)示例:
$ ~/opt/node-v6.7.0/bin/node t1.js
/home/rsp/node/test/prom-async/t1.js:3
let x = await f();
^
SyntaxError: Unexpected identifier
和第二个(正确的)示例将打印一个不同的错误:
$ ~/opt/node-v6.7.0/bin/node t2.js
/home/rsp/node/test/prom-async/t2.js:3
(async () => {
^
SyntaxError: Unexpected token (
了解它非常有用,因为不支持async
/ await
的节点版本不会给您带来有意义的错误,例如&#34; async / await不支持&# 34;或者类似的东西,不幸的是。
答案 1 :(得分:0)
确保您应该使用async
外部阻止,如:
async function() {
return await Promise.resolve('')
}
在节点7.6.0之后默认支持它。在7.6.0之前,您应该使用--harmony
选项来为它工作。
node -v
首先检查您的版本。
答案 2 :(得分:0)
首先,你还不太了解async-await。别担心,实际上很容易;但是你需要阅读文档才能使用那些东西。
更重要的是,您的代码存在的问题是await
个async
函数内部只能const { Client } = require('pg');
const moment = require('moment');
const _ = require('lodash');
const turf = require('@turf/turf');
const connString = // connection string
var collected = []
const CID = 300
const snaptimes = // array of times
var counter=0;
const client = new Client(connString);
function createArray(i,j) {
// return array of i arrays of length j
}
async function processSnaptime (snaptime) {
var info = {}; // an object of objects
// get information at given snaptime from database 1
const query1 = // parametrized query selecting two columns from database 1
const result1 = await client.query(query1, [CID,snaptime]);
var x = result1.rows;
for (var i = 0; i < x.length; i++) {
// store data from database 1 into info
// each row is an object with two fields
}
// line up subjects on the hole
const query2 = // parametrized query grabbing JSON string from database 2
const result2 = await client.query(query2, [CID,snaptime]);
const raw = result2.rows[0].JSON_col;
const line = createArray(19,0); // an array of 19 empty arrays
for (var i = 0; i < raw.length; i++) {
// parse JSON object and record data into line
}
// begin to collect data
var n = 0;
var g = 0;
// walk down the line
for (var i = 18; i > 0; i--) {
// if no subjects are found at spot i, do nothing, except maybe update g
if ((line[i] === undefined || line[i].length == 0) && g == 0){
g = i;
} else if (line[i] !== undefined && line[i].length != 0) {
// collect data for each subject if subjects are found
line[i].forEach(function(subject){
const query 3 = // parametrized query grabbing data for each subject
const result3 = await client.query(query3,[CID,subject,snaptime]);
x = result3.rows;
const y = moment(x[0].end_time).diff(moment(snaptime),'minutes');
var yhat = 0;
// the summation over info depends on g
if (g===0){
for (var j = i; j <= 18; j++){
yhat = moment.duration(info[j].field1).add(yhat,'m').asMinutes();
}
} else {
for (var j = i; j <= 18; j++){
if (i<j && j<g+1) {
yhat = moment.duration(info[j].field2).add(yhat,'m').asMinutes();
} else {
yhat = moment.duration(info[j].field1).add(yhat,'m').asMinutes();
}
}
}
collected.push([y,yhat,n,i]);
});
}
n+=line[i].length;
g=0;
}
// really rough work-around I once used for printing results after a forEach of queries
counter++;
if (counter===snaptimes.length){
console.log(counter);
console.log(collected);
}
}
async function run () {
for (let snaptime of snaptimes) {
await processSnaptime(snaptime);
}
}
/* to run all of them concurrently:
function run () {
let procs = [];
for (let snaptime of snaptimes) {
procs.push(processSnaptime(snaptime));
}
return Promise.all(procs);
}
*/
client.connect().then(run).then(() => client.end());
;你在任何功能之外做这件事。
首先,这里的解决方案最接近您编写的代码:
client.connect
then
会返回一个承诺,我会使用run
在client.end()
解决后致电run
。当 部分结束时,可以安全地调用async
。
await
是processSnaptime
函数,因此可以使用app.config['MYSQL_DATABASE_USER'] = 'root'
app.config['MYSQL_DATABASE_PASSWORD'] = ''
app.config['MYSQL_DATABASE_DB'] = 'UserList'
app.config['MYSQL_DATABASE_HOST'] = '172.17.0.3'
使代码更具可读性。 env | grep MYSQL
MYSQL_PORT_5123_TCP_ADDR=172.17.0.3
MYSQL_ENV_MYSQL_ROOT_PASSWORD=test
MYSQL_PORT_5123_TCP=tcp://172.17.0.3:5123
MYSQL_PORT_5123_TCP_PROTO=tcp
MYSQL_ENV_GOSU_VERSION=1.7
MYSQL_PORT_3306_TCP_PORT=3306
MYSQL_PORT_3306_TCP=tcp://172.17.0.3:3306
MYSQL_PORT_5123_TCP_PORT=5123
MYSQL_ENV_MYSQL_VERSION=5.7.18-1debian8
MYSQL_NAME=/site-metrics/mysql
MYSQL_PORT_3306_TCP_PROTO=tcp
MYSQL_PORT_3306_TCP_ADDR=172.17.0.3
MYSQL_ENV_MYSQL_MAJOR=5.7
MYSQL_PORT=tcp://172.17.0.3:3306
也是如此。
当然,我无法运行您的代码,所以我只能希望我没有犯任何错误。