Javascript forEach кажется неблокирующим - PullRequest
0 голосов
/ 10 июля 2019

При прочтении других постов здесь все согласны с тем, что forEach должен быть синхронным и блокирующим.

Однако я, должно быть, сделал что-то странное в своем коде, потому что это не так:

    var noDupes = false;  // should be true but force no inserts for now
    console.log('forEach');
    courses.forEach((course) =>
    {
        const promiseNoDupe = new Promise((resolve, reject) =>
        {
            dbo.collection("courses").findOne({ id: course.id }, (err, result) => 
            {
                if (err) throw err;
                if (result) { console.log('dupe'); return reject('dupe'); }
                console.log('nodupe');
                resolve('nodupe');
            });
        });

        noDupes &= promiseNoDupe.then(() =>
        {
            console.log('true promise');
            return true;
        }).catch(() =>
        {
            console.log('false promise');
            return false;
        });
    });
    console.log('End forEach');

    if (noDupes)
    {
        console.log('Inserting many');
        dbo.collection("courses").insertMany(courses, (err, result)  =>
        {
            if (err) return res.status(400).send(error.details[0].message);
            res.send(courses);
        });   
    }
    else
    {
        console.log('No Dupes allowed');
        res.status(400).send('Inserting duplicate ID not Allowed!');
    }

Вывод на консоль:

forEach
End forEach
No Dupes allowed
nodupe
true promise
nodupe
true promise

Конец forEach выполняется до того, как обещание будет выполнено, и до того, как будет проведена любая внутренняя обработка!Впоследствии логика ожидания обещания обрабатывается раньше времени.

Я не уверен, что происходит не так, но я пытаюсь дождаться завершения всех проверок в forEach, прежде чем фиксировать какие-либо новые записи.

1 Ответ

0 голосов
/ 10 июля 2019

Спасибо charlietfl за то, что он направил меня к map () и Promise.all ().

Вот рабочий код:

    var dupePromises = courses.map((course) => 
    {
        return new Promise((resolve, reject) =>
        {
            dbo.collection("courses").findOne({ id: course.id }, (err, result) => 
            {
                if (err) throw err;
                if (result) return reject(false);
                resolve(true);
            });
        }).then(() =>
        {
            return true;
        }).catch(() =>
        {
            return false;
        });
    });

    Promise.all(dupePromises).then((results) =>
    {
        if (results.every((isnotDupe) => { return isnotDupe /* == true */ }))
        {
            dbo.collection("courses").insertMany(courses, (err, result)  =>
            {
                if (err) return res.status(400).send(error.details[0].message);
                res.send(courses);
            });
        }
        else{
            res.status(400).send('Inserting duplicate ID not Allowed!');        
        }
    });
}
...