0

我有一组 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);
  });
});
4

1 回答 1

1

考虑将每个请求映射到 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;
  });
})();
于 2019-01-13T23:46:39.997 回答