javascript - forEach 循环中的 NodeJs 函数需要在转到下一项之前完成

标签 javascript node.js loops foreach

我有一个 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
...

最佳答案

对于requestmysql,您可以使用Promise支持的包,即:request-promisemysql2。为了保证顺序执行,您可以这样做:

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连接池,例如:

// 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]);

关于javascript - forEach 循环中的 NodeJs 函数需要在转到下一项之前完成,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55566562/

相关文章:

c - 确定要使用的正确循环

javascript - 在两个 div 之间画一条线(多个连接)

javascript - 如何访问包内的 meteor 包名称?

node.js - 我应该在哪里存储访问 token

javascript - 三重条件 do while 循环

javascript - Angular.forEach 不返回对象中的最后一项

javascript - 在 Angular JS 中获取 HTTP 请求的值

javascript - Svg 和 Highcharts?

javascript - 你如何替换 Aurelia 中的 HttpClient?

node.js - Mongodb atlas + node.js 在本地工作,但在推送到 Heroku 时停止