各位大神,我是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,而不是数据库查询后的赋值。
我想了很久,不知道这种情况该如何解决,貌似异步的方式无法解决这样的情况啊,。请教各位大神,像这种同步的流程和需求该如何转化成异步进行呢?是我的思路需要转变还是另有其他办法?
感觉按照异步的思路,data.query
这个方法应该设计成:
var data = {
query: function (sql, callback){} //多一个callback,在处理完结果后的回调。
}
但是我真的觉得这样的方式好奇怪啊,var result = data.query('select * from xxxx');
这样更容易让别人看懂啊。大家有什么办法能让它这样实现吗?
用 ThinkJS 可以很好的解決這個問題
@welefen 多谢指点,我找个时间去研究一下thinkjs,不过我还是想知道,用什么方式能解决这个问题,thinkjs解决这个问题的思路大致是什么捏?
@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