我正在解析 CSV 并处理每条记录,以使用 Mongoose 将其插入到我的 MongoDB 中。我已经正确地从 CSV 中获取了一个数组,但是当我开始使用 forEach (和 async/await)对其进行迭代时,它就停在那里了。
这是我的代码:
const csv = require('csv-parser');
const fs = require('fs');
const Customer = require('../../app/models/Customers');
const projects = [];
const processRecords = async () => {
try {
const usableProjects = projects.filter((project) => project['cust_number customer']);
const customerNames = [...new Set(usableProjects.map((item) => item['Parent Name']))];
await customerNames.forEach(async (customerName) => {
console.log('Point 1');
const existingCustomer = await Customer.find({Name: customerName});
console.log('Point 2'); //<======= THIS CODE IS NEVER REACHED
if (existingCustomer.length > 0) {
console.log(`${customerName} already exists. Skipping...`);
return;
}
const customerRecord = usableProjects.find((project) => project['Parent Name'] === customerName);
const newCustomer = {
Name: customerName,
Source: 'CSV',
Initials: customerRecord.Initials,
Code: customerRecord.Codename,
};
const newCustomerRecord = await Customer.create(newCustomer);
if (newCustomerRecord) {
console.log(`Customer ${newCustomerRecord._id} created`);
}
});
} catch (err) {
console.log(err);
}
};
fs.createReadStream('customer_table.csv')
.pipe(csv())
.on('data', async (data) => projects.push(data))
.on('end', async () => {
processRecords();
});
这是输出:
Point 1
Point 1
Point 1
Point 1
Point 1
Point 1
Point 1
Point 1
Point 1
Point 1
Point 1
Point 1
Point 1
我知道这可能与我未处理更正的同步/异步代码有关。但我一直无法修复它。提前致谢。
最佳答案
首先,让我们将 try-catch
放在 Customer.find()
上
(为了清楚起见,我将简化您的代码。并且我会将 Customer.find()
替换为 f()
)
async function success() { return "Hurrah!" }
async function failure() { throw new Error("Oops!") }
const customerNames = [1, 2, 3]
const processRecords1 = async (f) => {
try {
await customerNames.forEach(async (customerName) => {
try {
console.log('Point 1');
const existingCustomer = await f()
console.log('Point 2', existingCustomer);
// ...
} catch (err) {
console.log('Point 3', err);
}
});
} catch (err) {
console.log('Point 4', err);
}
};
setTimeout(() => processRecords1(success), 0);
输出:
Point 1
Point 1
Point 1
Point 2 Hurrah!
Point 2 Hurrah!
Point 2 Hurrah!
如您所见,如果f = success
则达到“Point 2”。所以这是第一个问题:您的 Customer.find()
失败并且您没有看到异常。
让我们尝试从 f()
抛出异常,只是为了证明这一点......
setTimeout(() => processRecords1(failure), 100);
输出:
Point 1
Point 1
Point 1
Point 3 Error: Oops!
Point 3 Error: Oops!
Point 3 Error: Oops!
是的,如果f()
失败,我们永远不会到达“第2点”。但现在我们确实在“第 3 点”中看到了一个错误。所以我们可以到此为止。
但是让我们尝试在 processRecords()
的顶层捕获异常并到达“第 4 点”。
正如已经提到的,forEach()
不返回值。让我们尝试一下map()
const processRecords2 = async (f) => {
try {
await customerNames.map(async (customerName) => {
console.log('Point 1');
const existingCustomer = await f()
console.log('Point 2', existingCustomer);
// ...
});
} catch (err) {
console.log("Point 4", err);
}
};
setTimeout(() => processRecords2(failure), 200);
输出:
Point 1
Point 1
Point 1
Uncaught (in promise) Error: Oops!
Uncaught (in promise) Error: Oops!
Uncaught (in promise) Error: Oops!
运气不好。这是因为 map()
确实返回一个值,但它是一个 Array
,而不是 Promise
。您不能 await
获取 Promise-s 数组,但可以使用 Promise.all()
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all
const processRecords3 = async (f) => {
try {
await Promise.all(customerNames.map(async (customerName) => {
console.log('Point 1');
const existingCustomer = await f()
console.log('Point 2', existingCustomer);
// ...
}));
} catch (err) {
console.log("Point 4", err);
}
};
setTimeout(() => processRecords3(failure), 300);
输出:
Point 1
Point 1
Point 1
Point 4 Error: Oops!
Point 4 Error: Oops!
Point 4 Error: Oops!
那个。将 await customerNames.forEach(...)
替换为 await Promise.all(customerNames.map(...)
就可以了。
关于javascript - Nodejs 和 Mongoose : Await stops loop,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59507374/