节点js foreach完成功能

Node js foreach done function

不用setTimeout,foreach完成后应该用什么?

app.post('/grid', function(req, res){
   getResults(req.body.idarray, function(callback){
       res.send(callback);
   });
});
function getResults(userIds, callback) {
    var totalresult = [];
    userIds.forEach(function (user) {
        sequence
            .then(function (next) {
                db.query('SELECT given FROM books WHERE user_id = ?', [user.userId], function (err2, result) {
                    if (err2) throw err2;
                    next(err, result);
                });
            })
            .then(function (next, err, books) {
                db.query('SELECT received FROM encycs WHERE user_id = ?', [user.userId], function (err3, result2) {
                    if (err3) throw err3;
                    next(err, result2, books);
                });
            })
            .then(function (next, err, books, encycs ) {
                Calculation(books, encycs, function (cb) {
                    totalresult.push(cb);
                });
                next();
            });
    });
    setTimeout(function() {
        console.log(totalresult);  // output ok.
        return callback(totalresult); // returning as expected
    }, 2000);
}

我不知道 totalresult.length 是什么。所以我无法检查长度。

因此,根据您的用例,您需要以某种方式调用回调并将 totalresult 传递给它,因为那是您的外部代码,即预期路径中的代码。 为此,您可以在调用第三个 .then 语句的下一个之前调用回调。就这样。

        ...
        .then(function (next, err, books, encycs ) {
            Calculation(books, encycs, function (cb) {
                totalresult.push(cb);
            });
            callback(totalresult);
            next();
            //console.log(totalresult); //output OK.
        });

这可能有效。

更新 1

很难理解您的代码。追不上它的逻辑。我建议你使用 Promises 方法。我准备了那个可能有效的解决方案。它可能包含很少的错误,但它代表了您要实现的目标以及如何实现的主要思想。

app.post("/grid", (req, res) => {
    getResults(req.body.idarray)
        .then(data => {
            res.status(200).json(data);
        })
        .catch(err => {
            console.error("Error occured", err);
            res.status(500).json(err);
        });
});

function getResults(userIds) {
    let promises = userIds.map(loadCalculation);
    //this will wait until all loadings are done
    return Promise.all(promises);
}

function loadCalculation(user) {
    //parallel loading of the books and encycs
    return Promise.all([loadBooks(user), loadEncycs(user)])
        .then(results => {
            let books = results[0];
            let encycs = results[1];

            let totalresult = [];

            Calculation(books, encycs, function (cb) {
                totalresult.push(cb);
            });

            return totalresult;
        });
}

function loadBooks(user) {
    return makeQuery('SELECT given FROM books WHERE user_id = ?', user);
}

function loadEncycs(user) {
    return makeQuery('SELECT received FROM encycs WHERE user_id = ?', user);
}

function makeQuery(query, user) {
    return Promise((resolve, reject) => {
        db.query(query, [user.userId], function (err, result) {
            if(err) {
                reject(err);
            } else {
                resolve(result);
            }
        });        
    });
}

请注意,这不是从数据库中加载数据的真正高效方式,至少,我确信您有可能通过单个查询加载所有书籍和百科全书,因为您是使用SQL,真是灵活的语言。