我正在嘗試讀取和修改一些 csv 檔案。對于一個 csv 檔案,我撰寫的代碼如下:
const csv = require('csv-parser');
const fs = require('fs');
const results = [];
const resultsFiltered = [];
fs.createReadStream('csvTest/2005.csv')
.pipe(csv())
.on('data', (data) => results.push(data))
.on('end', () => {
// Filter results
for (i=0; i<results.length; i ) {
if (results[i]['Points:2'] == 0) {
resultsFiltered.push([results[i]['Points:0'], results[i]['Points:1'], results[i]['displacement:2']]);
}
}
console.log('results filtered: ', resultsFiltered);
});
這很好用,但是當我嘗試遍歷多個檔案時,我得到了奇怪的結果。這是代碼:
const csv = require('csv-parser');
const fs = require('fs');
const dataFolder = 'csvTest/';
let results, resultsFiltered, stringified;
function filterData(_file) {
results = [];
resultsFiltered = [];
console.log('filtering');
fs.createReadStream(dataFolder _file)
.pipe(csv())
.on('data', (data) => results.push(data))
.on('end', () => {
// Filter results
for (i=0; i<results.length; i ) {
if (results[i]['Points:2'] == 0) {
resultsFiltered.push([results[i]['Points:0'], results[i]['Points:1'], results[i]['displacement:2']]);
}
}
console.log('done');
return resultsFiltered;
});
}
const filesList = fs.readdirSync(dataFolder);
function main() {
for (i=0; i<filesList.length; i ) {
console.log(filterData(filesList[i]));
}
}
main();
我知道它可以通過 async/await 來解決,但是我嘗試使用它的所有方法都沒有成功。我總是在控制臺中得到與上面的基本代碼相同的輸出:
filtering
undefined
filtering
undefined
filtering
undefined
done
done
done
而不是想要的
filtering
done
resultsFiltered
filtering
done
resultsFiltered
filtering
done
resultsFiltered
在這種情況下應該如何使用 async/await?
uj5u.com熱心網友回復:
你得到 undefined 因為你的函式沒有 return 陳述句。如果您仔細觀察,您使用的 return 陳述句實際上是在一個回呼函式中。您可以做的是承諾您的功能并使用異步等待。
const csv = require("csv-parser");
const fs = require("fs");
const dataFolder = "csvTest/";
let results, resultsFiltered, stringified;
function filterData(_file) {
return new Promise(res => {
results = [];
resultsFiltered = [];
console.log("filtering");
fs.createReadStream(dataFolder _file)
.pipe(csv())
.on("data", data => results.push(data))
.on("end", () => {
// Filter results
for (i = 0; i < results.length; i ) {
if (results[i]["Points:2"] == 0) {
resultsFiltered.push([
results[i]["Points:0"],
results[i]["Points:1"],
results[i]["displacement:2"]
]);
}
}
console.log("done");
res(resultsFiltered);
});
});
}
const filesList = fs.readdirSync(dataFolder);
async function main() {
for (const file of filesList) {
let result = await filterData(file);
console.log(result);
}
}
main();
嗯,這應該作業。
uj5u.com熱心網友回復:
您將需要轉換您的操作以回傳一個能夠等待結果的承諾
PS不要忘記通過監聽錯誤事件并拒絕承諾來處理錯誤。
function filterData(_file) {
results = [];
resultsFiltered = [];
console.log('filtering');
return new Promise((resolve) => {
fs.createReadStream(dataFolder _file)
.pipe(csv())
.on('data', (data) => results.push(data))
.on('end', () => {
// Filter results
for (i = 0; i < results.length; i ) {
if (results[i]['Points:2'] == 0) {
resultsFiltered.push([
results[i]['Points:0'],
results[i]['Points:1'],
results[i]['displacement:2'],
]);
}
}
console.log('done');
resolve(resultsFiltered)
});
});
}
const filesList = fs.readdirSync(dataFolder);
async function main() {
for (i = 0; i < filesList.length; i ) {
console.log(await filterData(filesList[i]));
}
}
uj5u.com熱心網友回復:
此代碼中存在多個可能導致問題的問題。
主要的邏輯問題是這些流都是異步的,并且您的代碼沒有跟蹤這些流中的任何一個何時完成讀取。你return resultsFiltered;在.on('end', ...)回呼中,所以你沒有從你的filterData()函式中回傳任何東西(這就是你得到的原因undefined),而只是從那個無處可去的回呼中回傳。
因此,當您遍歷這些流時,您會同時處理許多流,并且不知道它們何時全部完成,也無法從中獲取所有資料。
您還遇到未宣告的區域變數的問題,這將導致它們成為意外的全域變數并且它們可能相互沖突。
為了解決主要的邏輯問題,這是一個有用的地方,可以引入一個 Promise,該 Promise 將跟蹤每個流何時完成,并讓您將資料作為 Promise 的已解決值或錯誤作為拒絕原因:
function filterData(_file) {
const results = [];
const resultsFiltered = [];
return new Promise((resolve, reject) => {
fs.createReadStream(dataFolder _file)
.pipe(csv())
.on('data', (data) => results.push(data))
.on('end', () => {
// Filter results
for (let i = 0; i < results.length; i ) {
if (results[i]['Points:2'] == 0) {
resultsFiltered.push([results[i]['Points:0'], results[i]['Points:1'], results[i]['displacement:2']]);
}
}
resolve(resultsFiltered);
}).on('error', reject);
});
}
然后,您可以使用該承諾來跟蹤回圈中的內容:
const filesList = fs.readdirSync(dataFolder);
async function main() {
for (let i = 0; i < filesList.length; i ) {
const result = await filterData(filesList[i]);
console.log(result);
}
}
main().then(() => {
console.log("done");
}).catch(err => {
console.log(err);
});
請注意,這對您的代碼有其他幾個修復:
它
error在您的流上添加了一個事件處理程式,該處理程式拒絕承諾,從而使您有機會跟蹤和處理錯誤。您的原始代碼忽略了錯誤。這會為您的所有變數添加本地宣告,
const這let是絕對必需的。您的代碼沒有宣告i回圈中使用的任一變數,這將導致它們成為隱式變數并可能相互沖突。這會對流進行排序,因此它們不會一次全部進行,并且可以讓您保持結果井井有條。
Promise.all()通過收集所有的 Promise 并使用它來跟蹤它們,代碼也將被撰寫為并行運行(如果有足夠的資源可用) 。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/468119.html
標籤:javascript 节点.js 异步等待
