【问题标题】:How to load variables before page renders in node.js?如何在 node.js 中呈现页面之前加载变量?
【发布时间】:2013-06-30 07:43:36
【问题描述】:

我的问题是如何确保我的变量在页面被渲染之前被加载?我将 node.js 与 express 和everyauth 一起使用。

这是代码:

app.get('/', function(req, res) {
   app.locals.rep = global.repos;
   res.render('index'); 
});

当前,页面已加载,但包含变量的段落为空,并且出现错误:“无法读取未定义的属性 '...' [...]”。当我刷新页面时,内容就会流入。

index.jade

extends layout
block content
  h1= title
  - if (!everyauth.loggedIn)
    a(href="/auth/github") Login with github
  - else
    h3
      a(href='/logout') Logout
      h3 GitHub User Data
      - each r in rep
        p= r.name
        p= r.description

这是我设置 repos 变量的地方:

var repos;
global.repos = [];

everyauth.github
.appId(config.gh_clientId)
.appSecret(config.gh_secret)
.findOrCreateUser( 函数 (sess, accessToken, accessTokenExtra, ghUser) {

if (typeof usersByGhId[ghUser.id] === 'undefined') {

  usersByGhId[ghUser.id] = addUser('github', ghUser);

  var options = { 
            host: "api.github.com", 
            path: "/users/cmarius02/repos",
            method: "GET",
            headers: {
               "User-Agent": "github-connect" 
            }
  };

  var request= https.request(options, function(response){
    var body='';
    response.on("data", function(chunk){
      body+=chunk.toString("utf8");
    });

    response.on("end", function(){
      var json=JSON.parse(body);

      // console.log(json);  

      global.repos = [];
      for (var k in json)
        if ({}.hasOwnProperty.call(json, k)) {
          global.repos.push({
            name: json[k].name,
            description: json[k].description
          });
        }
    });
  });
  request.end();
  return usersByGhId[ghUser.id];

} else {
  return usersByGhId[ghUser.id];
}   })

.redirectPath('/');

这是我使用 node.js 的第一天,所以请耐心等待。提前谢谢你。

【问题讨论】:

  • 什么是global.repos?显示它的定义位置。在启动前配置服务器时,您通常还会设置app.locals
  • 您也可以发表您的看法吗?
  • 如果我是你,我会在整个 GitHub API 调用中添加一些日志记录,然后查看它是在向你的服务器发出第一个请求之前还是之后被调用的。这应该可以帮助您确定问题发生在哪里。报告您的发现,我会尽力提供进一步帮助 :) 您确定在服务器首次加载时调用了 load repos 函数吗?如果没有人登录?
  • GitHub API 请求仅在按下登录按钮时完成,如果那是您所要求的。 console.log() 证实了这一点。

标签: node.js express


【解决方案1】:

我使用passport而不是everyauth,但我认为方法应该类似

Express 使用中间件链接代码,每个中间件负责调用下一个(即使他们不知道是哪个)

我会这样做:

    app.all ('*', function (req,res,next) {
      // Add the user from the session
      if req.user?
          res.locals.session_user = req.user
      // Add the flash messages
      res.locals.flash_messages = req.flash()

      next()
    });

    app.get('/', function(req, res) {
      res.render('index'); 
    });

app.all 表示该路由将匹配 get、put 和 post 请求。 * 是匹配所有路由的正则表达式,因此第一个回调将在所有路由之前调用

req.user 由护照填写,我想每个auth 都有类似的东西。

res.locals 允许您将信息传递给视图。然后,在视图中,您可以将元素引用为 this.session_user (我不使用jade,但您明白了)。

另请注意,使用相同的方法,我将请求之间的闪烁传递给视图。

顺序很重要!并且 next() 向您保证,在前一个尚未解决之前,不会处理您的实际路线。如果需要,可以在该方法的另一个回调中调用 next。

【讨论】:

  • 它的反应方式相同。看起来它是并行进行变量设置和渲染的。有没有办法绑定这两个命令?
  • 我还添加了 'while (app.locals.z != 1) { app.locals.rep = global.repos; app.locals.z = 1; } ' 在 'res.render(...)' 之前,但仍然没有结果。
  • 我读到过,everyauth 可以选择使用 Promise... 我给你的方法有点同步。在第一个调用 next() 之前,不会调用第二个路由,但可能 req.user 不是对象,而是对对象的承诺。检查值在做什么 console.log typeof req.user 和类似的东西。对于承诺,这​​是一个链接stackoverflow.com/questions/8761230/whats-everyauth-promise
  • 谢谢埃尔南。但我决定改用护照。我可以给你一个项目的链接吗?
  • 遗憾的是,Marius,它不是一个开源项目,但我提取了必要的部分,并提供了一些关于我如何在这个要点中订购我的代码的提示(不知道是好是坏,但它对我有用)。有任何疑问,尽管问:) gist.github.com/hrajchert/5935329
【解决方案2】:

通过使用 Express 中间件,您可以通过以下方式覆盖渲染:

  app.use(function(req, res, next) {
    // Grap render
    var _render = res.render;

    // Override logic
    res.render = function(view, options, cb) {
      // Add logic (Example)
      if (!options.foo) {
        options.bar = true
      }

      // Original call
      _render.call(this, view, options, cb)
    }
    next()
  })

【讨论】:

    猜你喜欢
    • 2019-07-23
    • 2021-10-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多