【问题标题】:How can I pass Express.js variables to MongoDB functions?如何将 Express.js 变量传递给 MongoDB 函数?
【发布时间】:2020-08-26 08:02:42
【问题描述】:

我正在使用ExpressEJS 和 MongoDB 开发 blogging application(单击链接查看 GitHub 存储库)。

我为帖子制作了一个简单的寻呼机。

在帖子中 controller 我有:

exports.getPosts = async (req, res, next) => {

  const posts = await Post.find({}, (err, posts) => {

      const perPage = 10;

      const currPage = req.query.page ? parseInt(req.query.page) : 1;

      const postsCount = posts.length;

      const pageCount = Math.ceil(postsCount / perPage);

      const pageDecrement = currPage > 1 ? 1 : 0;

      const pageIncrement = currPage < pageCount ? 1 : 0;

      if (err) {
        console.log("Error: ", err);
      } else {
        res.render("default/index", {
          moment: moment,
          layout: "default/layout",
          website_name: "MEAN Blog",
          page_heading: "XPress News",
          page_subheading: "A MEAN Stack Blogging Application",
          currPage: currPage,
          pageDecrement: pageDecrement,
          pageIncrement: pageIncrement,
          posts: posts,
        });
      }
    })
      .sort({ created_at: -1 })
      .populate("category")
      .limit(perPage)
      .skip((currPage - 1) * perPage);
};

视图中的寻呼机:

<% if (posts) {%>
  <div class="clearfix d-flex justify-content-center">
    <div class="px-1">
        <a class="btn btn-primary <%= pageDecrement == 0 ? 'disabled' : '' %>" href="/?page=<%= currPage - pageDecrement %>">&larr; Newer Posts</a>
    </div>

    <div class="px-1">
        <a class="btn btn-primary <%= pageIncrement == 0 ? 'disabled' : '' %>" href="/?page=<%= currPage + pageIncrement %>">Older Posts &rarr;</a>
    </div>
  </div>
<% } %>

问题

来自控制器的.limit(perPage) 行在控制台(Git bash)中给出了错误perPage is not defined

不起作用的解决方案

很明显,我可以将这两行移到const posts上方

const perPage = 5;
const currPage = req.query.page ? parseInt(req.query.page) : 1;

但我可以const postsCount = posts.length;(我也需要在视图中)做同样的事情。

目标

我正在尝试使有关分页的代码的 sn-p 可重用(如果可能的话,就像一个插件),因为我需要为按类别过滤的帖子以及列表分页在应用程序的管理部分发布。

我做错了什么?

【问题讨论】:

  • 我没有运行代码,但我认为perPage 变量是正确的范围。尝试在const posts之前定义它。
  • 检查这些答案,他们可以帮助你Pagination Mongoose

标签: javascript node.js express ejs mean-stack


【解决方案1】:

正如评论正确指出的那样,这似乎是范围界定问题。

exports.getPosts = async (req, res, next) => {
  // getPosts local scope
  const posts = await Post.find({}, (err, posts) => {
      // ... local scope
      const perPage = 10;

      const currPage = req.query.page ? parseInt(req.query.page) : 1;

      const postsCount = posts.length;

      const pageCount = Math.ceil(postsCount / perPage);

      const pageDecrement = currPage > 1 ? 1 : 0;

      const pageIncrement = currPage < pageCount ? 1 : 0;

      if (err) {
        console.log("Error: ", err);
      } else {
        res.render("default/index", {
          moment: moment,
          layout: "default/layout",
          website_name: "MEAN Blog",
          page_heading: "XPress News",
          page_subheading: "A MEAN Stack Blogging Application",
          currPage: currPage,
          pageDecrement: pageDecrement,
          pageIncrement: pageIncrement,
          posts: posts,
        });
      }
      // ... local scope ended
    })
      .sort({ created_at: -1 })
      .populate("category")
      // perPage == undefined
      .limit(perPage)
      .skip(currPage - 1)) * perPage;
};

const perPage 移动到const posts 上方,它将在正确的范围/上下文中。

exports.getPosts = async (req, res, next) => {
  const perPage = 10;
  // getPosts local scope
  const posts = await Post.find({}, (err, posts) => {
      // ... rest of func
    });
  // .. rest of func
};

【讨论】:

  • 此解决方案解决了一个问题,但留下/创建了其他问题:我有一个使用 posts 变量的 postsCount 变量。
  • 您可以使用本地范围引用外部范围,但不能反过来。这篇文章可以比我更好地解释这一点:scotch.io/tutorials/understanding-scope-in-javascript
【解决方案2】:

也许如果你检查这个组件,你可以通过看看它是如何工作的来解决你的问题

Mongoose Paginate

$ npm install mongoose-paginate

/**
* querying for `all` {} items in `MyModel`
* paginating by second page, 10 items per page (10 results, page 2)
**/

MyModel.paginate({}, 2, 10, function(error, pageCount, paginatedResults) {
 if (error) {
   console.error(error);
 } else {
   console.log('Pages:', pageCount);
   console.log(paginatedResults);
 }
}

【讨论】:

    【解决方案3】:

    正如其他 cmets 所解释的那样。这可能只是范围的问题。

    exports.getPosts = async (req, res, next) => {
      const perPage = 10; // enable you to use perPage inside getPosts()
      let postsCount = 0; // let, to enable you to use/reassigned postsCount inside getPosts()
      const posts = await Post.find({}, (err, posts) => {
        // ...
        postsCount = posts.length; // updates the variable with the correct count
        // ...
        if (err) {
            console.log("Error: ", err);
          } else {
            res.render("default/index", {
              //...
              posts: posts,
              postsCount: posts.length, // for explicit postsCount in the view
    
            });
          }
    
      });
    
      // ..
    
    
    

    因为您的视图中已经有 posts,所以您在视图中遇到了postsCount 的问题

    <% if (posts) {%>
      ...
    <% } %>
    

    我认为您可以像使用其他视图一样在视图中使用posts.lengthpostsCounts(例如pageIncrement、currPage、pageIncrement);

    【讨论】:

    • 我已经这样做了,使用var postsCount = 0;,因为我无法更改常量的值。
    • 你好@harold-pogi,欢迎来到 SO!下次请确保不仅仅是发布代码,而是解释为什么这个解决方案可能有效以及出了什么问题。很有帮助!
    • 虽然此代码可以解决 OP 的问题,但最好包含关于您的代码如何解决 OP 问题的说明。这样,未来的访问者可以从您的帖子中学习,并将其应用到他们自己的代码中。 SO 不是编码服务,而是知识资源。此外,高质量、完整的答案更有可能获得支持。这些功能,以及所有帖子都是独立的要求,是 SO 作为一个平台的一些优势,使其与论坛区分开来。您可以编辑以添加其他信息和/或使用源文档补充您的解释。
    • 谢谢。我已经更新了我的答案,还包括解释并添加了postsCount
    【解决方案4】:

    为什么你同时使用回调和等待。似乎你需要查看异步/等待和承诺。你可以做的如下:

    exports.getPosts = async (req, res, next) => {
      const currPage = req.query.page ? parseInt(req.query.page) : 1;
      const perPage = 10;
      try {
        const posts = await Post.find({})
          .sort({ created_at: -1 })
          .populate("category")
          .limit(perPage)
          .skip((currPage - 1) * perPage).exec();
    
        const postsCount = posts.length;
    
        const pageCount = Math.ceil(postsCount / perPage);
    
        const pageDecrement = currPage > 1 ? 1 : 0;
    
        const pageIncrement = currPage < pageCount ? 1 : 0;
        res.render("default/index", {
          moment: moment,
          layout: "default/layout",
          website_name: "MEAN Blog",
          page_heading: "XPress News",
          page_subheading: "A MEAN Stack Blogging Application",
          currPage: currPage,
          pageDecrement: pageDecrement,
          pageIncrement: pageIncrement,
          posts: posts,
        });
      } catch (err) {
        console.log("Error: ", err);
        // add proper error handling here 
        res.render('default/error', {
          err
        });
      }
    };
    

    【讨论】:

    • 我认为您的 Post.find() 缺少 errposts 参数。
    • 如果使用异步等待,则无需传递回调
    • UnhandledPromiseRejectionWarning: ReferenceError: err is not defined at exports.getPosts (C:\Users\Asus\Desktop\XPressBlog\controllers\front-end\posts.js:23:3) 第 23 行:if (err) {.
    • 尝试更新代码,它使用 try catch 进行错误处理,同时也关注 async/await 和错误处理
    【解决方案5】:

    我最近发现postsCount = posts.length 计算帖子之后 它们受到.skip((currPage - 1) * perPage) 的限制,所以pageIncrement 变量“方程”变为:

    let pageIncrement = postsCount >= perPage ? 1 : 0;
    

    所以我在控制器中得到:

    exports.getPosts = async (req, res, next) => {
    
        const perPage = 5;
    
        const currPage = req.query.page ? parseInt(req.query.page) : 1;
    
        let postsCount = 0;
    
        const posts = await Post.find({}, (err, posts) => {
    
                postsCount = posts.length;
    
                let pageDecrement = currPage > 1 ? 1 : 0;
    
                let pageIncrement = postsCount >= perPage ? 1 : 0;
    
                if (err) {
                    console.log('Error: ', err);
                } else {
                    res.render('default/index', {
                        moment: moment,
                        layout: 'default/layout',
                        website_name: 'MEAN Blog',
                        page_heading: 'XPress News',
                        page_subheading: 'A MEAN Stack Blogging Application',
                        currPage: currPage,
                        posts: posts,
                        pageDecrement: pageDecrement,
                        pageIncrement: pageIncrement
                    });
                }
            })
            .sort({
                created_at: -1
            })
            .populate('category')
            .limit(perPage)
            .skip((currPage - 1) * perPage);
    };
    

    在视图中:

    <a class="btn btn-primary <%= pageDecrement == 0 ? 'disabled' : '' %>" href="/?page=<%= currPage - pageDecrement %>">&larr; Newer Posts</a>
    

    <a class="btn btn-primary <%= pageIncrement == 0 ? 'disabled' : '' %>" href="/?page=<%= currPage + pageIncrement %>">Older Posts &rarr;</a>
    

    除非有等于perPage x N 的帖子数量,否则这很好用,其中N 是一个整数,在这种情况下,“旧帖子”按钮被禁用一页为时已晚。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-12-20
      • 2011-06-21
      • 1970-01-01
      • 2020-07-28
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多