[英]Parsing large CSV and streaming rows of promises
在嘗試 ZF7B44CFFAFD5C52223D5498196C8A2E7BZ 和 csv 時有點混淆,為每一行發出 http 請求,並讓一切執行並以“正確”順序登錄到控制台。 最終,我認為我沒有正確地包裝我的承諾,或者......?
const getUserByEmail = async (email) => {
const encodedEmail = encodeURIComponent(email);
try {
const response = await http.get(`users?email=${encodedEmail}`);
const userId = response.data.data[0] && response.data.data[0].id;
return (userId ? userId : `${email} not found`);
} catch (error) {
console.error('get user error: ', error);
}
};
const run = async () => {
console.log('==> Reading csv ...');
const promises = [];
const readStream = fs.createReadStream('import-test.csv')
.pipe(csv.parse({ headers: true }))
.on('error', (error) => console.error('stream error: ', error))
.on('data', (row) => {
promises.push(getUserByEmail(row.email));
})
.on('end', rowCount => {
console.log(`==> Parsed ${rowCount} rows from csv ...`);
})
await Promise.all(promises)
.then(values => console.log(values))
console.log('==> End of script')
};
run();
我正在嘗試/期望上面的代碼獲取 csv 的每一行,將每個 http 調用(一個承諾)推送到一系列承諾,並按照我期望的順序執行/記錄到控制台。
這是我的實際 output:
==> Reading csv...
[]
==> End of script
==> Parsed 10 rows from csv ...
這就是我所期待的:
==> Reading csv...
==> Parsed 10 rows from csv ...
[
QyDPkn3WZp,
e75KzrqYxK,
iqDXoEFMZy,
PstouMRz3y,
w188hLyeT6,
g18oxMOy6l,
8wjVJutFnh,
fakeEmail@fakeDomain.com not found,
QEHaG3cp7d,
y8I4oX6aCe
]
==> End of script
對我來說最大的問題是在“==> 腳本結束”之后記錄了任何內容,這向我表明,我無法很好地掌握所有先前事件何時/為什么按它們的順序記錄。
最終——我還沒有到達那里——我還想將這些請求緩沖/計時到每分鍾 100 次,否則我將受到這個特定的 API 的速率限制。
謝謝!
孔 readStream 一直await Promise.all(promises)
是同步的 - data
事件是異步的並在另一個事件循環中填充承諾,因此當你調用 Promise.all 時承諾是一個空數組 - 你不是在等待 Promise.all - 你不是在等待 ZA5A3F0F287A4779AZ.all結束。 您可能希望將邏輯放在結束事件中,而不是像這樣
const run = async () => {
console.log('==> Reading csv ...');
const promises = [];
const readStream = fs.createReadStream('import-test.csv')
.pipe(csv.parse({ headers: true }))
.on('error', (error) => console.error('stream error: ', error))
.on('data', (row) => {
promises.push(getUserByEmail(row.email));
})
.on('end', async rowCount => {
await Promise.all(promises)
.then(values => console.log(values))
console.log('==> End of script')
})
}
go 關於它的另一種更簡單的方法是使用異步迭代器 readStream 有一個可以使用的symbol.asyncIterator
const run = async () => {
console.log('==> Reading csv ...');
let rowCount = 0
const promises = []
const readStream = fs.createReadStream('import-test.csv')
.pipe(csv.parse({ headers: true }))
for await (let row of readStream) {
rowCount++
promises.push(getUserByEmail(row.email));
}
console.log(`==> Parsed ${rowCount} rows from csv ...`)
await Promise.all(promises).then(console.log)
console.log('==> End of script')
}
我會進一步限制並發性並執行以下操作:
const run = async () => {
console.log('==> Reading csv ...');
const result = []
const readStream = fs.createReadStream('import-test.csv')
.pipe(csv.parse({ headers: true }))
for await (let row of readStream) {
result.push(await getUserByEmail(row.email))
}
console.log(result)
console.log('==> End of script')
}
如果您想提高異步迭代器的並發性,請查看這篇文章,但要小心。 使用此方法時結果可能出現故障
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.