简体   繁体   English

如何停止执行直到函数完成

[英]How to stop execution until function finishes

I'm working on an e-commerce web app using NodeJS and MongoDB (Mongoose).我正在使用 NodeJS 和 MongoDB (Mongoose) 开发电子商务 Web 应用程序。
I have a get route that will show products in shopping cart, and I'm struggling because I need one function to complete before continuing with the rest of the code.我有一个将在购物车中显示产品的 get 路线,我很挣扎,因为在继续执行其余代码之前我需要完成一个功能。
The function pushes items to an array, and then I try to render a view passing that array, but the array goes away empty.该函数将项目推送到一个数组,然后我尝试渲染一个传递该数组的视图,但该数组消失了。

Here's my code.这是我的代码。

router.get('/cart', function (req, res) {
  User.findOne({ username: req.user.username }, function (err, doc) {
    // This is the array that needs to be passed
    const prodAndQty = [];
    const prodEntries = Object.entries(doc.shoppingCart);
    // This is the function that I need to complete before continuing
    prodEntries.forEach(function (entry) {
      Product.findOne({ id: entry[0] }, function (err, doc) {
        prodAndQty.push([doc, entry[1]]);
      });
    });
    if (err) { console.log(err); }
    else {
      // If I log here, the array is empty.
      console.log(prodAndQty);
      if (doc) {
        res.render('cart', { doc: doc, qty: prodEntries.length, products: prodAndQty });
      } else {
        res.render('cart', { doc: null, qty: 0, products: null });
      }
    }
  });
});

If I log the array before rendering, the array is empty.如果我在渲染之前记录数组,则数组为空。
Also, in the terminal, the array is logged even before the Mongoose queries executes.此外,在终端中,甚至在 Mongoose 查询执行之前就记录了该数组。

Terminal log终端日志

If I log the array inside the function that is pushing, the array is filled correctly, but it's too late to be useful.如果我在正在推送的函数中记录数组,则数组已正确填充,但为时已晚,无法使用。

Any help would be greatly appreciated.任何帮助将不胜感激。

You need something called as promise-based behavior for your code.您的代码需要称为promise-based behavior Please refer :请参考:

  1. async functions 异步函数
  2. promise承诺

Try something like this -尝试这样的事情 -

router.get('/cart', async function (req, res) {
    try {
        const doc = await User.findOne({ username: req.user.username });

        if(!doc) {
            res.render('cart', { doc: null, qty: 0, products: null });
        }

        const prodEntries   = Object.entries(doc.shoppingCart);

        // Instead of one by one searching, I used `in` operator (you can do one by one too, if you want)
        const entires       = prodEntries.map((prod) => {
            return prod[0];
        })

        const prodAndQty    = await Product.find({ id : { $in : entires }});
        // TODO - Modify this prodAndQty array as you want

        res.render('cart', { doc: doc, qty: prodEntries.length, products: prodAndQty });

    } catch(err) {
        throw new Error(err);
    }
}

In your approach, what happens is, you are using callback function which does not wait for the code to execute inside forEach and it just go ahead and returns the response.在您的方法中,发生的情况是,您正在使用回调函数,该函数不会等待代码在 forEach 内部执行,它只是继续并返回响应。

Async-await is a syntactic sugar on the top of that which let you write code in a way, so it seems it's executing in serial manner. Async-await是一种语法糖,它允许您以某种方式编写代码,因此它似乎是以串行方式执行的。 Another method is to use promises .另一种方法是使用promises

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM