Nodejs forEach функция не ожидает асин c функций - PullRequest
0 голосов
/ 26 февраля 2020

Я пытаюсь получить 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;

1 Ответ

2 голосов
/ 26 февраля 2020

Есть несколько проблем с вашим асинхронным кодом внутри al oop.

  1. a .forEach() l oop не ждет await. Вы должны использовать for l oop или while l oop, если хотите, чтобы он ожидал await.
  2. Вы не используете await на db.collection("photos").countDocuments({"id": photo.id}, {limit: 1});.
  3. Вы не используете await на db.collection("photos").insertOne(photo).
  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;
...