ExpressJS res.render() error (JSON.stringify can't work on circular reference)
这有什么不对?
它导致
1 | Converting circular structure to JSON |
错误,(导致会话元素具有循环用户引用。)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | <wyn> 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 || [] } }); } }); }; </wyn> |
我在
1 2 3 4 5 6 7 8 | 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); ... |
就结构而言,这就是我期望会话的样子:
1 2 3 4 5 6 7 8 9 10 11 | { 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 } } |
但这是我发现的:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 | { 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'发送值,但最终只有一个(这就是循环引用的来源)。
看起来会话正用于将对象传输到视图。
这是我唯一的中间件(它只从会话中读取):
1 2 3 4 5 6 7 | function requiresAuthentication(req, res, next){ if (req.session.user){ next(); } else { next(new Error('Unauthorized. Please log in with a valid account.')) } } |
并且我唯一一次修改req.session就在这条路线上:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | 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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | 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") |
如果我将用户注释掉部分,则会呈现,否则我会遇到此
UPDATE
所以在连接eclipse和v8调试器之后,我一直在逐步完成代码,我知道会话和用户对象的混搭在哪里,
在
utils.union最终将用户对象的成员混合到会话中,从而导致循环引用。我只是不确定为什么(诚然可能是我的代码)
这是在视图中修改会话数据的问题。
经过多次挖掘,我发现这是2.5.8中部分处理方式的错误。 我提交了一个问题,然后是一个补丁。 (如果有人在将来需要此信息),因为npm仍在提供Express 2.5.8 AFAIK。
感谢您的帮助@freakish和@Ryan