V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
yimity
V2EX  ›  Node.js

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

  •  
  •   yimity · 2015-06-18 10:32:01 +08:00 · 3473 次点击
    这是一个创建于 3480 天前的主题,其中的信息可能已经有所发展或是发生改变。
    node express MongoDB mongoose

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

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

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

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

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

    谢谢大家啊。
    11 条回复    2015-07-22 08:49:31 +08:00
    jarlyyn
        1
    jarlyyn  
       2015-06-19 17:16:24 +08:00   ❤️ 1
    按mvc的话是controller取回所有数据丢给view渲染的。

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

    另外,边栏这种应该是有缓存的吧?
    yimity
        2
    yimity  
    OP
       2015-06-19 17:22:19 +08:00
    @jarlyyn 关键问题是边栏和其他数据取得话都要异步,我想的是,是不是有个思路不用异步这种方式。
    jarlyyn
        3
    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
        4
    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
        5
    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
        6
    jarlyyn  
       2015-06-19 17:36:59 +08:00
    反正是自己写着玩的,本职工作写代码还是拍黄片为主。

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

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

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

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

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

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

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

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

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

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

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


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

    毕竟我是玩儿nodejs的,不知道这样做是否能符合你的业务需求。
    yimity
        8
    yimity  
    OP
       2015-06-23 08:16:41 +08:00
    @jarlyyn 十分感谢,这种确实是一个非常好的思路,不过这种思路我还要理解一下。谢谢啊。
    broadliyn
        9
    broadliyn  
       2015-07-20 11:13:29 +08:00
    可不可以试试promise then?
    broadliyn
        10
    broadliyn  
       2015-07-20 11:15:19 +08:00
    yimity
        11
    yimity  
    OP
       2015-07-22 08:49:31 +08:00
    @broadliyn 谢谢啊,但是 promise 其实还是一样的思路。只不过换了种写法。我想要的是,类似于多表联合查询这种。不知道能不能实现。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2734 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 11:40 · PVG 19:40 · LAX 03:40 · JFK 06:40
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.