NodeJS:按顺序写入多个GET请求的文件响应

时间:2019-01-13 23:40:38

标签: node.js json get writefile appendfile

我有一个URL数组,我需要调用每个URL并将响应以有效JSON顺序写入文件。例如[resp1, resp2, resp3,...]。 但是,在下面的代码中,我将响应随机写入文件中。例如[resp3]resp1,resp2,。如何防止在包含许多URL的foreach中发生这种情况(以致于我无法手动下一步)?

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 个答案:

答案 0 :(得分:2)

考虑将每个请求映射到Promise,然后改为使用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;
  });
})();