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

请问这种情况如何修改同步代码到异步风格?

  •  
  •   loginv2 · 2015-08-29 19:34:52 +08:00 · 3239 次点击
    这是一个创建于 3161 天前的主题,其中的信息可能已经有所发展或是发生改变。
    业务逻辑需要

    function func1 (){
    if (条件 1 ){
    return 1;
    }

    if (条件 2 ){
    return 2;

    .......



    }
    其中一个条件 或者全部条件变成了一个异步查询的时候 要如何修改代码? 谢谢
    7 条回复    2015-09-01 01:24:04 +08:00
    future0906
        1
    future0906  
       2015-08-29 19:41:19 +08:00   ❤️ 1
    要保证逻辑的准确性没有简单的办法;先将业务需要判断的逻辑收集起来,分为 pre check 和 post check ;异步之前先执行 pre check 异步返回后再执行一次 pre check 和 post check ;如果异步的操作只是检查的话,可以直接 return 掉;如果异步涉及到状态改变,需要通知 remote peer rollback 。
    loginv2
        2
    loginv2  
    OP
       2015-08-29 19:48:57 +08:00
    这里的逻辑其实是一个登录验证(之前没验证 现在要加上)(除了登录还有其他权限的判断),返回的状态只有 成功和失败
    但是使用了 sqlite3 模块的操作,这个操作是异步的,回调内部返回 并不能对外层方法产生返回影响

    而外层是一个模块中的一个方法 被调用在 主体业务逻辑中(这里很复杂 不好修改)
    于是目前处于束手无策的状态 Nodejs 在这方面没有一个好点的解决方案么
    ljbha007
        3
    ljbha007  
       2015-08-29 19:57:19 +08:00
    https://gist.github.com/CarlLee/66a667775fbd94802173

    思路
    1.每个异步操作结束检查一下其他操作结束没有 如果没有就什么都不干
    2.如果都操作完了 则进行总的条件判断
    ljbha007
        4
    ljbha007  
       2015-08-29 20:08:18 +08:00
    https://gist.github.com/CarlLee/9fb961270a4f50dd3eee

    这个是用 async 写起来代码结构可读性会高很多 不过实际上逻辑是一样的
    loginv2
        5
    loginv2  
    OP
       2015-08-29 20:09:30 +08:00
    @ljbha007
    @future0906
    懂了,感谢两位
    magicdawn
        6
    magicdawn  
       2015-08-29 23:33:16 +08:00
    co + generator 大法好

    var func1Async = co.wrap (function *(){
    if (条件一){
    return yield 查询 1 ();
    }

    if (条件二){
    return yield 查询 2 ();
    }
    });

    只要查询 1 & 查询 2 反悔 promise or thunk 就 OK, 现在你的 func1Async () 就是自动返回 promise 的
    harttle
        7
    harttle  
       2015-09-01 01:24:04 +08:00
    Promise/deferred 模式用来解决异步资源的同步问题通常很有效。包括 jQuery 、 AngularJS 、 mongoose 都在内部实现了 Promise 。在项目中引入 Promise 可以试试这个实现: https://github.com/petkaantonov/bluebird

    之后你的代码写起来可能是这样的:

    Promise
    .all ([getResource1 (), getResource2 ()])
    .spread (function (data1, data2 ){
    if (data1 && data2 ){
    // do sth.
    }
    });
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   1046 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 19:23 · PVG 03:23 · LAX 12:23 · JFK 15:23
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.