NodeJS: запись в файл ответов на несколько запросов GET по порядку

У меня есть массив URL-адресов, и мне нужно вызвать каждый из них и записать ответ на файл в правильном порядке в формате JSON. Например, [resp1, resp2, resp3,...], Однако в приведенном ниже коде я получаю ответы, записанные в файл в случайном порядке. Например, [resp3]resp1,resp2,, Как я могу предотвратить это в пределах foreach со многими URL-адресами (чтобы я не мог перейти к ним вручную)?

fs.writeFile('my_file.json', "[", (err) => {
  if (err) throw err;
});
urls.forEach((url, index) => {
  https.get(url, (resp) => {
    let data = '';
    resp.on('data', (chunk) => {
      data += chunk;
    });
    resp.on('end', () => {
      let output = data;
      (index == urls.length) ? output += ']' : output += ',' 
      fs.appendFileSync('my_file.json', output, (err) => {
        if (err) throw err;
      });
    });
  }).on("error", (err) => {
    console.log("Error: " + err.message);
  });
});

1 ответ

Рассмотрите возможность сопоставления каждого запроса с обещанием, а затем используйте Promise.all вместо этого, а затем записать в файл только один раз:

const urlProms = urls.map(url => new Promise((resolve, reject) => {
  https.get(url, (resp) => {
    let data = '';
    resp.on('data', (chunk) => {
      data += chunk;
    });
    resp.on('end', () => resolve(data));
  })
  .on('error', reject);
}));
Promise.all(urlProms)
  .then((dataArr) => {
    fs.writeFile('my_file.json', JSON.stringify(dataArr), (err) => {
      if (err) throw err;
    });
  })
  .catch((err) => {
    // handle errors
  });

Создание / объединение строк JSON вручную редко является хорошей идеей. Если вам пришлось сделать это вручную, используйте async/await ждать каждой итерации по порядку, чтобы убедиться, что все вставлено в правильном порядке и что перекрывающиеся запросы не занимают слишком много памяти:

const getData = url => new Promise((resolve, reject) => {
  https.get(url, (resp) => {
    let data = '';
    resp.on('data', (chunk) => {
      data += chunk;
    });
    resp.on('end', () => resolve(data));
  })
  .on('error', reject);
});
(async () => {
  fs.writeFileSync('my_file.json', '[', (err) => {
    if (err) throw err;
  });
  for (let i = 0; i < urls.length; i++) {
    const data = await getData(urls[i]);
    fs.appendFileSync('my_file.json', data, (err) => {
      if (err) throw err;
    });
  }
  fs.appendFileSync('my_file.json', ']', (err) => {
    if (err) throw err;
  });
})();
Другие вопросы по тегам