我有一个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);
});
});
答案 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;
});
})();