ExpressJS res.render()错误(JSON.stringify无法在循环引用上工作)

时间:2012-03-05 03:47:49

标签: node.js express

这里有什么问题?

res.render('/somepage', {user:req.session.user})

导致

Converting circular structure to JSON
错误,(导致会话元素具有循环用户引用。)


exports.home =  function (req, res) {
    var entityFactory = new require('../lib/entity-factory.js').EntityFactory();
    entityFactory.get_job_task_lists({
        callback : function (err, job_task_lists) {
            res.render('home.jade', {
                        locals:{
                            title: 'Logged in.', 
                            user:req.session.user, // does not work
                            job_task_lists:job_task_lists || [] 
                        }
            });
        }
    });
};


我在node_modules/express/node_modules/connect/lib/middleware/session/memory.js

中添加了一些记录
MemoryStore.prototype.set = function(sid, sess, fn){
  var self = this;
  process.nextTick(function(){

    console.log(sess); //this is giving the output listed

    self.sessions[sid] = JSON.stringify(sess);
...

就结构而言,这就是我期望会话的样子:

{ lastAccess: 1330979534026,
  cookie: 
   { path: '/',
     httpOnly: true,
     _expires: Tue, 06 Mar 2012 00:32:14 GMT,
     originalMaxAge: 14399999 },
  user: // this is the object I added to the session
   { id: 1,
     username: 'admin',
     password: '8e3f8d3a98481a9073d2ab69f93ce73b',
     creation_date: Mon, 05 Mar 2012 18:08:55 GMT } } 

但这是我发现的:

{ lastAccess: 1330979534079, // new session
  cookie: 
   { path: '/',
     httpOnly: true,
     _expires: Tue, 06 Mar 2012 00:32:14 GMT,
     originalMaxAge: 14399999 },
  user:  // but here it is again, except now it's a mashup,
         // containing members it shouldn't have, like locals,
         // and, well, everything but the first 4 properties
   { id: 1,
     username: 'admin',
     password: '8e3f8d3a98481a9073d2ab69f93ce73b',
     creation_date: '2012-03-05T18:08:55.701Z',
     locals: 
      { title: 'Logged in.',
        user: [Circular], //and now it's circular
        job_task_lists: [Object] },
     title: 'Logged in.',
     user: [Circular],
     job_task_lists: [ [Object], [Object], [Object], getById: [Function] ],
     attempts: [ '/home/dan/development/aqp/views/home.jade' ],
     scope: {},
     parentView: undefined,
     root: '/home/dan/development/aqp/views',
     defaultEngine: 'jade',
     settings: 
      { env: 'development',
        hints: true,
        views: '/home/dan/development/aqp/views',
        'view engine': 'jade' },
     app: 
      { stack: [Object],
        connections: 6,
        allowHalfOpen: true,
        _handle: [Object],
        _events: [Object],
        httpAllowHalfOpen: false,
        cache: [Object],
        settings: [Object],
        redirects: {},
        isCallbacks: {},
        _locals: [Object],
        dynamicViewHelpers: {},
        errorHandlers: [],
        route: '/',
        routes: [Object],
        router: [Getter],
        __usedRouter: true },
     partial: [Function],
     hint: true,
     filename: '/home/dan/development/aqp/views/home.jade',
     layout: false,
     isPartial: true } }

node.js:201
        throw e; // process.nextTick error, or 'error' event on first tick
              ^
TypeError: Converting circular structure to JSON
    at Object.stringify (native)
    at Array.0 (/home/dan/development/aqp/node_modules/express/node_modules/connect/lib/middleware/session/memory.js:77:31)
    at EventEmitter._tickCallback (node.js:192:40)

查看用户对象是如何嵌套的?

  • 请注意,这次我没有使用'locals'明确发送值,但最终只有一个(这就是循环引用的来源。

看起来会话正用于将对象传输到视图。

这是我唯一的中间件(它只能从会话中读取):

function requiresAuthentication(req, res, next){
    if (req.session.user){
        next();
    } else {
        next(new Error('Unauthorized. Please log in with a valid account.'))
    }
}

并且我唯一一次修改req.session就在这条路线上:

app.post('/home', function (req,res,next) {
    var auth = require('./lib/authentication');
    auth.authenticate_user(req.body.user, function (user) {
        if (user){
            req.session.user = user;
            console.log('authenticated');
            res.redirect(req.body.redir || '/home');
            //next();
        } else {
            console.log('not authenticated');
            res.render('logins/new.jade', {title: 'Login Failed', redir:''})
        }
    });
});

我的应用程序中还没有其他功能,因为它还很年轻。我知道我自己并没有在任何地方破坏会议;我查了一下。

我做了一些测试,当我尝试在页面上使用局部变量时,这似乎只是一个问题。例如,这是我的观点home.jade

div(data-role="page")
    div(data-role="header")
        a(href='/logout', data-icon='delete', data-ajax="false") Log out
        h1= title
        a(href='/account', data-icon='info', data-ajax="false") Account

        != partial('user', user)


    each jtl in job_task_lists
        div(id=jtl.name, class = 'draggable_item', style='border:2px solid black;')
            #{jtl.name} - #{jtl.description} 
        a(data-icon='plus') 


    div(data-role="footer")
        h3 footer

script(src="/javascripts/home.js")

如果我将用户注释掉部分,则会呈现,否则我会遇到此Converting circular structure to JSON问题。

更新 所以在连接eclipse和v8调试器后,我一直在逐步完成代码,我知道会话和用户对象的混搭在哪里,

node_modules/connect/lib/middleware/session/session.js

中的

utils.union最终将用户对象的成员混合到会话中,从而导致循环引用。我只是不确定为什么(诚然可能是我的代码)

1 个答案:

答案 0 :(得分:3)

这是在视图中修改会话数据的问题。

经过多次挖掘,我发现这是2.5.8中部分处理方式的错误。我提交了issue,随后又提交了patch。 (如果有人在将来需要此信息),因为npm仍在提供Express 2.5.8 AFAIK。

感谢您的帮助@freakish和@Ryan