【问题标题】:Nodejs forEach function doesn't wait for async functions [duplicate]Nodejs forEach 函数不等待异步函数 [重复]
【发布时间】:2020-02-26 09:07:32
【问题描述】:

我正在尝试获取 json,检查 mongodb 是否存在重复,如果不存在,则将数据插入 mongodb。

问题是循环非常快,无需等待重复检查和插入。

我在这里做错了什么?

const fetch = require('node-fetch');
var MongoClient = require('mongodb').MongoClient;


async function fetchPhotos() {
    MongoClient.connect("mongodb://localhost:27017", async function (err, dbo) {
        const db = dbo.db('mydb')
        if (err) throw err;
        for (var i = 1; i < 100; i++) {
            await fetch(`domain.com/?page=${i}`)
               .then(res => res.json())
                .then((response) => {
                    response.forEach(photo => {
                        console.log("checking if there is duplicate: " + photo.id);

                        var exists =  db.collection("photos").countDocuments({"id": photo.id}, {limit: 1});

                        if (exists === 1) {
                            console.log("dupl found, next!");

                        } else {
                            db.collection("photos").insertOne(photo, function (err, res) {
                                if (err) throw err;
                                console.log("1 document inserted");
                            });
                        }
                    });
                });

        }

    });
}

module.exports.fetchPhotos = fetchPhotos;

【问题讨论】:

  • 这能回答你的问题吗? Using async/await with a forEach loop
  • 永远不要在普通的异步回调中写入if (err) throw err;。它完全没用,并且不能被您的任何代码捕获。编写真正的错误处理。

标签: node.js mongodb loops async-await


【解决方案1】:

循环中的异步代码存在一些问题。

  1. .forEach() 循环不会等待await。如果您希望它等待await,则必须使用for 循环或while 循环。
  2. 您没有在db.collection("photos").countDocuments({"id": photo.id}, {limit: 1}); 上使用await
  3. 您没有在 db.collection("photos").insertOne(photo) 上使用 await
  4. 不要在同一个控制流中混合普通的回调和承诺。这使得安全编码和正确处理错误变得非常困难。
  5. 您在许多地方缺少适当的错误处理。

您可以重组整个事情以使用数据库的承诺接口,然后通过照片对迭代进行排序并简化如下:

const fetch = require('node-fetch');
var MongoClient = require('mongodb').MongoClient;

async function fetchPhotos() {
    const dbo = await MongoClient.connect("mongodb://localhost:27017");
    const db = dbo.db('mydb');
    for (let i = 1; i < 100; i++) {
        let response = await fetch(`http://example.com/?page=${i}`);
        let data = await response.json();
        for (let photo of data) {
            console.log("checking if there is duplicate: " + photo.id);
            let cnt = await db.collection("photos").countDocuments({"id": photo.id}, {limit: 1});
            if (cnt > 0) {
                console.log("dupl found, next!");
            } else {
                await db.collection("photos").insertOne(photo);
                console.log("photo inserted");
            }
        }
    }
}

// caller of fetchPhotos() gets a promise that tells you if the 
// operation completed or had an error
module.exports.fetchPhotos = fetchPhotos;

【讨论】:

  • 非常感谢。假设我在 for 循环中有以下几行:const analyzeData = await recognize.analyze(photo.urls.regular); 函数 identify.analyze 是一个异步 axios 发布请求。为什么 console.log(analyzeData);返回未定义?
  • @demonoid - 您必须显示实际代码。 recognize.analyze 似乎没有返回正确的值/承诺。如果您需要进一步的帮助,请发布一个显示该情况代码的新问题。
猜你喜欢
  • 2020-09-23
  • 1970-01-01
  • 2021-01-11
  • 2023-03-13
  • 2018-10-23
  • 1970-01-01
  • 1970-01-01
  • 2021-08-27
  • 2019-11-28
相关资源
最近更新 更多