网站有边栏,边栏的数据应该怎么查?

2015-06-18 10:32:01 +08:00
 yimity
node express MongoDB mongoose

现在有个场景,一个网站,左右分栏的。然后主区域的数据例如分类啊,文章列表啊,可以回调去查数据库。比如查完分类在这个回调中再查文章列表。

但是边栏的数据,其实不是很重要,应该用什么样子的逻辑去查数据库呢?

使用 分类查完的回调中查文章列表,文章列表查完的回调中查边栏的数据,边栏有五个数据,再回调五次?这样的逻辑吗?

也就是,每个数据来源都要在回调中查,然后等所有的数据查完了,再返回嘛?

大家有什么建议的?或者更好的方式?

谢谢大家啊。
3319 次点击
所在节点    Node.js
11 条回复
jarlyyn
2015-06-19 17:16:24 +08:00
按mvc的话是controller取回所有数据丢给view渲染的。

我自己写过一个简单的东西,把需要的数据绑定到view/widget,渲染的时候事先去取一下。

另外,边栏这种应该是有缓存的吧?
yimity
2015-06-19 17:22:19 +08:00
@jarlyyn 关键问题是边栏和其他数据取得话都要异步,我想的是,是不是有个思路不用异步这种方式。
jarlyyn
2015-06-19 17:28:40 +08:00
@yimity

用异步没啥不好,不想异步么用async搞。

我觉得关键的问题不是在异步上,而是在怎么让这个过程自动化。不要让回调充斥整个代码,打乱逻辑。

我自己给express写了个扩展,最后的话控制器大概是这样的:

app.post('/api/create',Run(
web.IF(Form.isValidated('createuser'))(
'createuser'
),
Http.notFoundIf(Form.isPending('createuser')),
Form.doJsonErrors('createuser')
));
app.post('/api/update',Run(
web.IF(Form.isValidated('updateuser'))(
'updateuser'
),
Http.notFoundIf(
Form.isPending('updateuser'),
Form.isError('updateuser','id')
),
Form.doJsonErrors('updateuser')
));

app.post('/api/toggle',Run(
web.IF(Form.isValidated('toggleuser'))(
'toggleuser'
),
Http.notFoundIf(
Form.isPending('toggleuser'),
Form.isError('toggleuser','id')
),
Form.doJsonErrors('toggleuser')
));
app.post('/api/setpassword',Run(
web.IF(Form.isValidated('setpassword'))(
'setpassword'
),
Http.notFoundIf(
Form.isPending('setpassword'),
Form.isError('setpassword','uid')
),
Form.doJsonErrors('setpassword')
));
app.get('/api/users',Run(
Http.notFoundIfNot(Form.isValidated('listuser')),
MVC.doJsonData('usersjson')
));

app.get('/api/admin_history_recently',Run(
MVC.doJsonData('adminHistoryRecently')
));
app.load(__dirname+'/role/routers');
app.use(Run(Http.doNotFound('Page not found')));
//app.get('/index',Runtime(MVC.doRender('listuser')));
app.use(HttpError(404)(MVC.doRender('404')));
jarlyyn
2015-06-19 17:32:12 +08:00
视图里大概是这样的:

module.exports=function(app,web){
var MVC=web.MVC;
MVC.viewpath=__dirname+'/views/';
MVC.registerView('layouts/main');
MVC.registerView('404').setLayout('layouts/main');
//MVC.registerView('layoutName').bindData('dataName');
MVC.registerView('index').setLayout('layouts/main').bindData('homeslider');
//MVC.registerView('viewname').setLayout('layoutViewname').bindData('dataName');
}


然后绑定的数据是这样的

module.exports=function(app,web)
{
var MVC=web.MVC;
var models=web.models;
var _=web.libs.lodash;
var moment=web.libs.moment;
MVC.registerData('homeslider',function(callback,runtime){
callback(null,[
{
href:'#',
src:'/assets/images/air.jpg',
text:'空运',
},
{
href:'#',
src:'/assets/images/boat.jpg',
text:'海运',
},
]);
});
}

自己写着玩的东西,为了比较正常的方式去写一个类似cms的网站。
jarlyyn
2015-06-19 17:33:54 +08:00
表单这样:

module.exports=function(app,web)
{
var Form=web.Form;
Form.registerValidator('loginUser',function(callback,form,name,params){
if (form.hasError){return callback(null,true)}
if (form.get(name)=='webfoss')
{
form.uid=1;
return callback(null,true);
}
return callback(null,false)
});
Form.registerValidator('loginPassword',function(callback,form,name,params){
if (form.hasError){return callback(null,true)}
return callback(null,form.get(name)==123456);
});

Form.registerValidator('userExists',function(callback,form,name,params){
if (form.hasError){return callback(null,true)}
var query={where:{}}
query.where[name]=form.get(name);
web.models.userModel.find(query).success(
function(user){
form._userModel=user;
return callback(null,user?true:false);
}
);
});
Form.registerValidator('passwordExists',function(callback,form,name,params){
if (form.hasError){return callback(null,true)}
var query={where:{}}
query.where[name]=form.get(name);
web.models.passwordModel.find(query).success(
function(password){
form._passwordModel=password;
return callback(null,password?true:false);
}
)
.fail(function(err){
callback(err,false);
});
});

var loginForm=Form.registerForm('login');
loginForm.field('username').required('用户名必填').addValidator('loginUser','用户名错误');
loginForm.field('password').required('密码必填').addValidator('loginPassword','密码错误');
var createUserForm=Form.registerForm('createuser');
createUserForm.field('name').required('姓名必填');
createUserForm.field('username').required('用户名必填').addValidator('isEmail','信箱格式不对').addValidator(['seUnique',web.models.userModel,'username'],'用户名已经被使用');
createUserForm.field('password').required('密码不可为空');
createUserForm.field('passwordrepeat').required('密码不可为空').addValidator(['compare','password'],'密码不一致');

var getUpdateUnquieQuery=function(form,name){return {where:{'id':{'ne':form.get('id')}}};}
var updateUserForm=Form.registerForm('updateuser');
updateUserForm.field('name')
.required('姓名必填');
updateUserForm.field('username')
.required('用户名必填')
.addValidator('isEmail','信箱格式不对')
.addValidator(['seUnique',web.models.userModel,'username',getUpdateUnquieQuery],'用户名已经被使用');
updateUserForm.field('id')
.required('没有ID')
.addValidator('userExists','用户不存在');

var toggleUserStatusForm=Form.registerForm('toggleuser');
toggleUserStatusForm.field('id').required('没有ID').addValidator('userExists','用户不存在');

var setPassword=Form.registerForm('setpassword');
setPassword.field('uid').required('没有ID').addValidator('passwordExists','用户不存在');
setPassword.field('password').required('密码不可为空');
setPassword.field('passwordrepeat').required('密码不可为空').addValidator(['compare','password'],'密码不一致');

var listUserForm=Form.registerForm('listuser','get');
listUserForm.field('id');
listUserForm.field('name');
listUserForm.field('username');
listUserForm.field('sort').addValidator(['isIn',['name','username','id','createdAt','status']]);
listUserForm.field('status')
listUserForm.field('asc');
listUserForm.field('offset');
listUserForm.field('limit');

app.load(__dirname+'/role/forms');
}
jarlyyn
2015-06-19 17:36:59 +08:00
反正是自己写着玩的,本职工作写代码还是拍黄片为主。

把所有异步的部分做在类似model的类里。

把所有数据注册起来,在控制器里不要过多的关注异步的内容,以列表(顺序)和字典(并列)来代表每一步要做的任务。

逻辑层面要干净,脏东西写在其他代码里,由单元测试来负责正确性。
jarlyyn
2015-06-19 17:48:15 +08:00
不好意思,贴代码贴的太多了,回到主题。

我觉得你的问题不是取数据是异步还是同步的,这是技术细节问题。

你的问题是大量的回调代码破坏了本来能从代码中体现出的逻辑关系。

那我的处理方法就是把他们藏起来。

而页面本身,其实我的理解是你可以处理为

{
‘body’:{'template':'body.ejs','data':'bodydata'}
'widget':{'template':'sidebar.ejs','data':'sidedata'}
}

丢给处理数据的程序,返回

{
‘body’:'<div>....</div>',
'widget':'<div>...</div>',
}

这样的输出字符串,再在前台渲染。


异步获取数据的代码都注册到 'bodydata'和'sidedata'里,取数据库也要,缓存套数据库也好,不干扰主要逻辑。

毕竟我是玩儿nodejs的,不知道这样做是否能符合你的业务需求。
yimity
2015-06-23 08:16:41 +08:00
@jarlyyn 十分感谢,这种确实是一个非常好的思路,不过这种思路我还要理解一下。谢谢啊。
broadliyn
2015-07-20 11:13:29 +08:00
可不可以试试promise then?
broadliyn
2015-07-20 11:15:19 +08:00
yimity
2015-07-22 08:49:31 +08:00
@broadliyn 谢谢啊,但是 promise 其实还是一样的思路。只不过换了种写法。我想要的是,类似于多表联合查询这种。不知道能不能实现。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/199464

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX