javascript - forEach 循环中的 NodeJs 函数需要在转到下一项之前完成
问题描述
我有一个 Nodejs 脚本,其详细信息如下所示:
1)它向API请求获取城市列表,它将获取JSON数组。使用这个数组,我使用forEach
.
2)在每次迭代(第二次循环)中,我再次向 API 请求获取详细信息(大约 100 行)并将其插入mysql
数据库。
我的问题,如何使第一个循环中的函数(从哪里获取城市列表)等待完成,然后再转到下一个项目(城市)。我想制作一个有延迟的循环。
我的源代码:
const request = require('request');
var moment = require('moment');
var mysql = require('mysql');
var a = moment('2019-04-01');
var b = moment('2019-04-06');
const sleep = (waitTimeInMs) => new Promise(resolve => setTimeout(resolve, waitTimeInMs));
function timer(ms) {
return new Promise(res => setTimeout(res, ms));
}
var connection = mysql.createConnection({
host : 'localhost',
user : 'user1',
password : 'password',
database : 'local'
});
async function getURL(id_city,dates) {
var url = 'https://localhost/api/format/json/schedule/city/'+id_city+'/date/'+dates;
request(url, { json: true }, (err, res, body) => {
if (err) { return console.log(err); }
// console.log(body.status);
var item1 = body.schedule.data.item1;
var item2 = body.schedule.data.item2;
connection.connect();
connection.query('INSERT INTO schedule (city,item1,item2) values ("'+id_city+'","'+task1+'", "'+task2+'")', function (error, results, fields) {
if (error) throw error;
});
// connection.end();
});
}
async function getDate(id_city)
{
var end;
for (var m = moment(a); m.isBefore(b); m.add(1, 'days')) {
getURL(id_city,m.format('YYYY-MM-DD'));
await timer(1000); //making delay
}
}
async function main () {
var url = 'https://localhost/api/format/json/list_city';
connection.connect();
request(url, { json: true }, (err, res, body) => {
if (err) { return console.log(err); }
var list_city = body.city; //this is an array
var counter = 0;
list_city.forEach(function(city){
getDate(city.id, function(){
});//i need this to complete before go to next city
});
});//end request url
}
main();
我的期望(顺序):
city1
insert item a done...
insert item b done...
city2
insert item a done...
insert item b done...
insert item c done...
city3
...
解决方案
对于两者request
,mysql
您都可以使用受Promise
支持的包,即:request-promise
和mysql2
. 为了保证顺序执行,您可以执行以下操作:
const rp = require('request-promise');
const mysql = require('mysql2/promise');
// then in your getURL function
async function getURL(id_city,dates) {
var url = 'https://localhost/api/format/json/schedule/city/'+id_city+'/date/'+dates;
const body = await rp(url, { json: true })
const item1 = body.schedule.data.item1;
const item2 = body.schedule.data.item2;
const connection = await mysql.createConnection({host:'localhost', user: 'root', database: 'test'});
const [rows, fields] = await connection.execute('INSERT INTO schedule (city,item1,item2) values ("'+id_city+'","'+task1+'", "'+task2+'")');
}
// One await in getDate should do
async function getDate(id_city) {
var end;
for (var m = moment(a); m.isBefore(b); m.add(1, 'days')) {
await getURL(id_city,m.format('YYYY-MM-DD'));
}
}
用于处理错误async/await
:
try {
const body = await rp(url, { json: true })
} catch (e) {
// handle erorr
console.error(e);
// or rethrow error: throw e
}
为了提高效率,您可以使用mysql connection pool
:
// myPool.js
const mysql = require('mysql2');
// create pool
const pool = mysql.createPool({
host:'localhost',
user: 'root',
database: 'test',
connectionLimit: 10,
queueLimit: 0
});
// now get a Promise wrapped instance of that pool
const promisePool = pool.promise();
module.exports = () => promisePool;
// Then in your getURL
const getPool = require('./myPool');
async function getURL(id_city,dates) {
...
const pool = await getPool();
const [rows, fields] = await pool.execute('INSERT INTO schedule (city,item1,item2) values ("'+id_city+'","'+task1+'", "'+task2+'")');
...
还可以考虑使用prepared
语句。
connection.execute('SELECT * FROM `table` WHERE `name` = ? AND `age` > ?', ['Morty', 14]);
推荐阅读
- tensorflow - 如何将具有不同形状/尺寸的张量相乘?
- php - PHP/MySQL - 基于日期/时间的下一个/上一个按钮,具有重复的日期/时间
- automation - 在 ios 14 快捷方式中自动将图像从电子邮件保存到相册
- ios - Xcode 12 可以与 Xcode 11 共存吗?
- cgal - 带曲线边界的约束 Delaunay 三角剖分
- html - 如何将文本放在消息气泡的顶部
- python - 如何用定界符拆分我的字符串,但在数据中转义定界符?
- python - 即使输入是非整数,是什么让 hex() 正常工作?
- python - 在季节性分解中正确使用 Freq
- nearprotocol - 无符号整数的 NEAR 和安全数学