For Mongoose FindOne之前的循环结束

时间:2018-05-22 01:01:59

标签: node.js

关于如何解决这个问题,我现在已经搜索了一段时间(关闭和开启了几个星期)。 ATM我有它的工作,但它硬编码和looong。我有一个库存系统需要遍历UPC列表,然后通过Mongoose的FindOne查找每个UPC。我不确定在For循环结束之前是否正在调用和执行res.render行,或者FindOne是否未及时完成。我在“订单”中显示的唯一内容是在进入循环之前完成的联系信息。

我的所有经验都不在于node.js,所以这就是为什么我的代码看起来像它一样。

以下是我的代码:

app.post('/want', (req, res) => {
var order = "Contact:"+req.body.Contact+"\n";

for(var i = 100; i < 800; i++){
    if(req.body[i] > 0){
        Extract.findOne({upc: i}, function(err, extract){
            order += extract.name + '/' + extract.type + ' - ' + req.body[i];
        });
    }
}

res.render("order.hbs",{
    pageTitle: "Order Confirmation",
    order: order
});

});

2 个答案:

答案 0 :(得分:0)

我不是一个经验丰富的node.js开发人员,但如果我是你,我会尝试Promise.all来执行promise并获取结果数组或将UPC数组发送到mongo,在mongo中使用aggregate来获取结果

答案 1 :(得分:0)

你应该做什么

Mongoose支持其查询范围。你真的应该使用范围,例如

Extract.find({ upc: { $gt: 100, $lt: 800 } }).then((extracts) => {
    extracts.forEach((extract, i) => {
        let realIndex = i + 100;
        order += extract.name + '/' + extract.type + ' - ' + req.body[realIndex];
    });

    res.render("order.hbs",{
        pageTitle: "Order Confirmation",
        order: order
    });

}).catch(() => res.sendStatus(500));

你不该做什么

正如您所知,findOne是一个异步函数(这就是它需要回调的原因)。

为了得到正确的答案,您必须等待,直到完成所有异步调用。一种方法是使用promises。

e.g

app.post('/want', (req, res) => {
    let order = "Contact:"+req.body.Contact+"\n";
    const promises = [];

    for(let i = 100; i < 800; i++){
        if (req.body[i] > 0){
            promises.push(() => return new Promise((resolve, reject) => {
                Extract.findOne({upc: i})
                    .then(extract => resolve({ extract: extract, index: i}))
                    .catch(reject);
            });
        }
    }

    Promise.all(promises).then((values) => {
        values.forEach((value) => {
            order += value.extract.name + '/' + value.extract.type + ' - ' + req.body[value.index];
        }):

        res.render("order.hbs",{
            pageTitle: "Order Confirmation",
            order: order
        });
   }).catch(() => res.sendStatus(500));
});

我在这里所做的一开始可能看起来很棘手,所以让我在这里分解一下:

  • 我正在定义一个新的const数组(它的类型不会从数组更改为其他内容)。
  • 对于每个循环,我会将一个新的承诺推送到这个数组中。
  • 当所有承诺都完成时(这就是Promise.all所做的),我将进行字符串连接,然后返回。

我可以将Extract.findOne()推入数组中;但由于你需要字符串连接中的索引,我实际上是被迫创建一个新的promise,它将返回一个具有两个值的对象:extractindex