Node.js和Mongoose:等待停止循环

时间:2019-12-28 01:09:20

标签: javascript node.js mongodb mongoose async-await

我正在解析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 proccessRecords = 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 () => {
    proccessRecords();
  });

这是输出:

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

我知道这可能与我未处理的同步/异步代码有关。但是我无法修复它。预先感谢。

3 个答案:

答案 0 :(得分:0)

我同意@JaromandaX,因为每个都不支持诺言,并且不支持异步/等待。请改用map

答案 1 :(得分:0)

数组 ClassLoader classLoader = getClass().getClassLoader(); try { InputStream in = classLoader.getResourceAsStream("/assets/baseline_close_black_18dp.png"); Image image = new Image(in); ImageView imageView= new ImageView(image); } catch (Exception ex) { } 不返回任何内容,因此,您无法等待它们。如果您要等待一系列的诺言,那就去forEach吧。但是,请注意,应将其与map

结合使用
Promise.all

现在,这将并行运行所有item.fetch调用。在大多数情况下,这是首选方式。但是,如果要连续运行item.fetch调用,则应改用for循环。

async function example(arr) {
  await Promise.all(
    // Assume item.fetch() returns a promise
    arr.map(item => item.fetch())
  );
}

答案 2 :(得分:0)

首先,让我们将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 proccessRecords1 = 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(() => proccessRecords1(success), 0);

输出:

Point 1
Point 1
Point 1
Point 2 Hurrah!
Point 2 Hurrah!
Point 2 Hurrah!

如您所见,如果达到f = success的“点2”。因此,这是第一个问题:您的Customer.find()失败了,您看不到异常。 让我们尝试抛弃f(),只是为了证明重点...

setTimeout(() => proccessRecords1(failure), 100);

输出:

Point 1
Point 1
Point 1
Point 3 Error: Oops!
Point 3 Error: Oops!
Point 3 Error: Oops!

是的,如果f()失败,我们将永远无法到达“第2点”。但是现在我们确实在“第3点”中看到了一个错误。所以我们可以在这里停止。

但是,让我们尝试在顶级proccessRecords()上捕获异常,并进入“第4点”。 如前所述,forEach()不返回值。让我们尝试map()

const proccessRecords2 = 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(() => proccessRecords2(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 proccessRecords3 = 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(() => proccessRecords3(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(...),一切顺利。