Nodejs怎么在forEach里的所有mongoose的回调都执行完毕后, 才返回给客户端执行完毕?

Nodejs怎么在forEach里的所有mongoose的回调都执行完毕后, 才返回给客户端执行完毕?

docMen.forEach(function(o) {
Users.findOne({
“_id”: o.user //	,"_id": ObjectId(listId)
}, null, function(err, docUser) {
if (err) {
console.log(‘find docUser error!’);
}
docUser.money = docUser.money+1;
docUser.save(function(err) {
if (err) {
console.log(“save Lists setAnswer error!”);
} else {
console.log(“save Lists setAnswer OK!”);
}
});
});
});

		//res.send({
		//	ret: "OK"
		//});

怎么在forEach里的所有mongoose的回调都执行完毕后, 才返回给客户端执行完毕?


7 回复

要在 forEach 循环中确保所有 Mongoose 回调都执行完毕后再返回给客户端,可以使用 Promise 和 Promise.all 来管理异步操作。以下是具体的实现方法:

示例代码

const async = require('async'); // 如果需要使用 async 库来处理异步操作
const mongoose = require('mongoose');
const Users = mongoose.model('Users', new mongoose.Schema({}));

app.post('/update-users', (req, res) => {
    const docMen = [/* 假设这里有一个用户ID数组 */];

    const updatePromises = docMen.map((o) => {
        return new Promise((resolve, reject) => {
            Users.findOne({ "_id": o.user }, (err, docUser) => {
                if (err) {
                    console.log('find docUser error!');
                    reject(err);
                } else {
                    docUser.money = docUser.money + 1;
                    docUser.save((err) => {
                        if (err) {
                            console.log("save Lists setAnswer error!");
                            reject(err);
                        } else {
                            console.log("save Lists setAnswer OK!");
                            resolve();
                        }
                    });
                }
            });
        });
    });

    Promise.all(updatePromises)
        .then(() => {
            res.send({
                ret: "OK"
            });
        })
        .catch((err) => {
            res.status(500).send({
                ret: "Error",
                message: err.message
            });
        });
});

解释

  1. 创建 Promise 数组:首先将 docMen.forEach 替换为 map 方法,这样我们可以生成一个包含所有异步操作的 Promise 数组。
  2. 封装异步操作:每个 Promise 包含对 Users.findOne 的调用以及之后的 save 操作。如果任何操作失败,Promise 将被拒绝,并通过 reject(err) 抛出错误。
  3. 使用 Promise.allPromise.all 方法接收一个 Promise 数组,并等待所有这些 Promise 都完成(即全部成功或至少有一个失败)。只有当所有的 Promise 都成功时,才会调用 .then 方法。
  4. 返回结果:当所有 Promise 都成功时,发送 res.send({ ret: "OK" }) 给客户端。

这种方法确保了所有的 Mongoose 操作都在返回给客户端之前完成,避免了异步问题。


docMen.forEach(function(o) {
    // 略过
});

res.send({ret: 'ok'});

不太了解 mongoose 不过forEach是同步的,这样应该没有问题吧?

如果提前输出了,你要的解决方案的关键点应该不在forEach这里。

var Promise = require('bluebird')
    ;

Promise.each(docMen, function(o){
    return User.findOne({
        _id: o.user
    })
    .exec()
    .then(function(docUser){
        docUser.money = docUser.money+1;
        return Promise.promisify(docUser.save, docUser)();
    });
})
.then(function(){
    res.send({
        ret: 'OK'
    });
});

LZ看看这种用法行不行?

楼主,用 eventr 来处理这种并发回调吧

https://github.com/alsotang/eventr#map-array-to-another

直接用FOR i=docMen.length-1 的时候

                docUser.save(function(err) {
                    if (err) {
                        console.log("save Lists setAnswer error!");
                    } else {
                           res.send({    ret: 'OK'   });
                    }
                });

用async的map方法就解决了。可以去看下api就明白了!

要在 forEach 循环中的所有 Mongoose 回调都执行完毕后再返回给客户端,可以使用 async/awaitPromise.all 来确保所有的异步操作都完成。下面是一个示例代码:

const async = require('async');

docMen.forEach(async function(o) {
    try {
        let docUser = await Users.findOne({ "_id": o.user }).exec();
        docUser.money = docUser.money + 1;
        await docUser.save();
    } catch (err) {
        console.error("Error:", err);
    }
});

// 确保所有的 mongoose 操作都完成后才返回响应
Promise.all(docMen.map(async function(o) {
    try {
        let docUser = await Users.findOne({ "_id": o.user }).exec();
        docUser.money = docUser.money + 1;
        await docUser.save();
    } catch (err) {
        console.error("Error:", err);
    }
})).then(() => {
    res.send({
        ret: "OK"
    });
}).catch((err) => {
    console.error("Error:", err);
    res.status(500).send({
        ret: "Error",
        message: "An error occurred while processing the request."
    });
});

解释

  1. 异步循环: 使用 async/await 处理每个用户的查询和更新操作。
  2. Promise.all: 使用 Promise.all 来等待所有用户的操作完成。
  3. 错误处理: 在 try/catch 块中处理可能发生的错误,并在最终的响应中返回适当的错误信息。

这样就可以确保所有的 mongoose 操作都完成后再返回响应给客户端。

回到顶部