将MongoDB中的数据值传递给Node.js中的ejs Template

时间:2018-03-10 01:13:09

标签: javascript node.js express ejs

我有一个快速的应用程序,我正在使用ejs来呈现视图。例如,这是我的观点之一:

<a href="/admin/categories" class="list-group-item">
                            <span style="margin-right: 6px" class="glyphicon glyphicon-folder-close"></span>
                            Categories
                            <span class="badge categoriesCount"><%= catCount %></span> <!-- get data from mongo -->
                        </a>

在我的路线文件中,我从mongodb获取了值并尝试将它们传递到视图中,如:

router.get('/', (req, res) => {

let cat_count = 0,
    prod_count = 0,
    user_count = 0,
    order_count = 0;

Category.count({}, (err, count) => {
    if (!err) {
        cat_count = count;
        console.log('Cat count from db:\t' + count);
    } else {
        console.error('Error Fetching Categories Count:\t' + err);
    }
});

Products.count({}, (err, count) => {
    if (!err) {
        prod_count = count;
        console.log('Prod count from db:\t' + count);
    } else {
        console.error('Error Fetching Products Count:\t' + err);
    }
});

Users.count({}, (err, count) => {
    if (!err) {
        user_count = count;
        console.log('User count from db:\t' + count);
    } else {
        console.error('Error Fetching Users Count:\t' + err);
    }
});

Orders.count({}, (err, count) => {
    if (!err) {
        order_count = count;
        console.log('Orders count from db:\t' + count);
    } else {
        console.error('Error Fetching Orders Count:\t' + err);
    }
});

res.render('index', {
    catCount: cat_count,
    prodCount: prod_count,
    userCount: user_count,
    orderCount: order_count
  });
});

其中catCount是模板中变量的实际参数。这不起作用,我坚持用这个方法搞清楚。

我也尝试使用DOM querySelector('className').innerHTML,但这也行不通。

这是向我的模板发送值的最佳方式,我更喜欢ejs。 感谢。

1 个答案:

答案 0 :(得分:0)

您的代码无效,因为计数变量的值只会在回调运行后分配。处理回调时,您必须注意,当您运行main函数时,回调函数中的代码不会立即执行。你现在拥有的是以下内容:

// initialize variables
// execute Category.count({}) and call the function that you passed in when data is ready
// execute Products.count({}) and call the function that you passed in when data is ready
// execute Users.count({}) and call the function that you passed in when data is ready
// execute Orders.count({}) and call the function that you passed in when data is ready
// render

所有这5行代码将在瞬间运行,并且不等待直到调用这些回调函数。解决它的一种方法是将所有回调嵌套在一起:

router.get('/', (req, res) => {

  let cat_count = 0,
      prod_count = 0,
      user_count = 0,
      order_count = 0;

  Category.count({}, (err, count) => {
    if (!err) {
      cat_count = count;
      console.log('Cat count from db:\t' + count);

      Products.count({}, (err, count) => {
        if (!err) {
          prod_count = count;
          console.log('Prod count from db:\t' + count);

          Users.count({}, (err, count) => {
            if (!err) {
              user_count = count;
              console.log('User count from db:\t' + count);

              Orders.count({}, (err, count) => {
                if (!err) {
                  order_count = count;
                  console.log('Orders count from db:\t' + count);

                  res.render('index', {
                    catCount: cat_count,
                    prodCount: prod_count,
                    userCount: user_count,
                    orderCount: order_count
                  });
                } else {
                  console.error('Error Fetching Orders Count:\t' + err);
                }
              });
            } else {
              console.error('Error Fetching Users Count:\t' + err);
            }
          });
        } else {
          console.error('Error Fetching Products Count:\t' + err);
        }
      });
    } else {
      console.error('Error Fetching Categories Count:\t' + err);
    }
  });
});

然而,这非常混乱,在JavaScript中被称为回调地狱。这是Promises派上用场的地方。

以下是您可以做的事情:

router.get('/', (req, res) => {
  let queries = [
    Category.count({}), 
    Products.count({}), 
    Users.count({}), 
    Orders.count({})
  ];

  Promise.all(queries)
  .then(results => {
    res.render('index', {
      catCount: results[0],
      prodCount: results[1],
      userCount: results[2],
      orderCount: results[3]
    });
  })
  .catch(err => {
    console.error('Error fetching data:', err)
  });
});

对于Mongoose,当您不将函数作为第二个参数传递时,函数调用返回的值(例如Category.count({}))将是Promise。我们将所有这些未解决的Promise放在一个数组中,并调用Promise.all来解决它们。通过使用Promise.all,您将等待所有计数查询执行,然后再继续呈现index视图。在这种情况下,Mongoose函数调用的结果将按results数组的顺序存储在queries数组中。