请教思路,大家是如何用异步的方式处理同步的逻辑的呢?
发布于 9 年前 作者 echoloyuk 6187 次浏览 最后一次编辑是 8 年前 来自 问答

各位大神,我是Node.js的初学者,一直在实践和学习各种Node相关的东西,近期遇到一个较为疑惑的问题。我知道一些关于async之类的组件,它可以实现部分的同步逻辑,但是,我遇到了一个问题,貌似它们也不好解决,请教一下大家,像下面这样的逻辑大家该怎样处理呢?

需求:一个对象包含一个查询mysql数据库的方法,在查询完数据库之后,将查询结果进行处理之后return出来。

这样的一个需求在PHP,Java等同步式的语言中实现很简单,但是在我写Node的时候,发现这个存在很大的问题,下面是我的伪代码,说明了我的思路:

var async = require('async');
var mysql = require('mysql');
var data = {
  query: function (sql){
    var result;
    async.waterfall([
      function (next){ //先查询sql
        var conn = mysql.createConnection({...}); //建立一个连接
        conn.connect();
        conn.query(sql, function (err, rows, fields){ //查询数据库
          if (err)
            throw err;
          next(null, rows); //当结果查询完毕之后,继续执行下一个业务
        });
      }, function (rows, next){
        
        //....对rows进行相关的处理和操作
        console.log(1);
        //将处理的结果返回
        result = rows;
      }
    ]);
    console.log(2);
    return result; //在这里将结果返回出去
  }
}

上面的思路是想在返回结果并处理完之后,再return,即先console出1,再出2。然后在另外的模块中使用:

var result = data.query('select * from xxxx');

但是实际上的结果是result为undefined,即先console出了2,然后才是1,因为data.query()中先return了result,而不是数据库查询后的赋值。 我想了很久,不知道这种情况该如何解决,貌似异步的方式无法解决这样的情况啊,。请教各位大神,像这种同步的流程和需求该如何转化成异步进行呢?是我的思路需要转变还是另有其他办法?

13 回复

感觉按照异步的思路,data.query这个方法应该设计成:

var data = {
	query: function (sql, callback){} //多一个callback,在处理完结果后的回调。
}

但是我真的觉得这样的方式好奇怪啊,var result = data.query('select * from xxxx');这样更容易让别人看懂啊。大家有什么办法能让它这样实现吗?

用 ThinkJS 可以很好的解決這個問題

@welefen 多谢指点,我找个时间去研究一下thinkjs,不过我还是想知道,用什么方式能解决这个问题,thinkjs解决这个问题的思路大致是什么捏?

data.query(‘sql xxxxxx’,function(result){ do something }

也是很容易看明白的吧

来自酷炫的 CNodeMD

不然就用Promise

data.query('sql xxxx').then(function(data){
do something
});

来自酷炫的 CNodeMD

@lingmm 恩,是这样的。我只是在想,如果我想做一个中间层的data类,专门负责数据查询和传递(就像传统的MVC那样),回调的方式有点不太适应。试想,如果我的业务逻辑是这样的:

var result1 = data.query(sql1);
var result2 = data.query(sql2 + result1);
var result3 = data.query(sql3 + result2);
dosomething(result3);

用callback就感觉有点不好维护了。我还是想知道一下到底有没有方式能做成这样?还是异步本身这样的思路是要改变的。

建议你参考cnode的源代码

用co? 直接返回Promise. data.query是异步的啊.

@wewea 我去研究一下,能不能略微指点一二,怎么解决data.query的异步的问题呢

@wewea@vigoss1944 经过 一天的摸索,我渐渐发现,node.js这种异步的特性,应该从原理上不能彻底实现:

var result1 = data.query(sql1);
var result2 = data.query(sql2 + result1);
var result3 = data.query(sql3 + result2);

我估计应该是对异步的理解有误,看来貌似通过类似:

data.query(sql1, function (){
	data.query(sql2, function (){
		data.query(sql3, function (){
			//...
		})
	})
});

方式才是比较正确的方式,至于async或者promise,只能是上面这种嵌套换一种写法而已,并不能真正做到我希望的那样。

@i5ting 非常感谢大侠,我之前有看过您的那个帖子,但是当时没有遇到这个问题,简单看了一下,感触不深。又一次仔细看了一下,感觉收获很多啊。

其实我就是特别想在Node上写出像PHP那样的代码:

var rows = data.query('select * from xxx');

直接获得查询的结果,不过现在看来,对于异步来说,这样的方式显然不行。

可以用async或者promise/A+完成大部分同步需要的逻辑,只是,从代码的方式和逻辑思维上,有些比较难理解罢了。

@echoloyuk 其实没什么,大部分现在做node的都不是一开始就习惯异步回调思维的,做久了就习惯了,人嘛,又不是木头。其实我特别习惯回调的思维方式,代码块一折叠起来觉得很明白。不过现在也习惯了用co拉平回调,node也在尽量拉平代码。 自豪地采用 CNodeJS ionic

回到顶部