但初学nodejs也很容易错误的使用回调
最常见的就是没有异步的回调
function foo(data,callback){ console.log(data); if(data=='data'){//如果参数等于data则回传0 console.log("do something"); callback(0); }else{//否则则回传错误信息 callback('数据错误'); } } foo('data',function(err){ console.log(err); });这样做虽然达到了预期效果,但是其本质还是一个同步的方法,
如果不用回调的话,代码会更易读更易维护
function foo(data){ console.log(data); if(data=='data'){//如果参数等于data则返回0 console.log("do something"); return 0; }else{//否则则返回错误信息 return '数据错误'; } } var result=foo('data'); console.log(result);如果do something是比较复杂的计算,需要异步处理的话,则可以像下面这样修改
function foo(data,callback){ process.nextTick(function(){ console.log(data); if(data=='data'){//如果参数等于data则回传0 console.log("do something"); callback(0); }else{//否则则回传错误信息 callback('数据错误'); } }); } foo('data',function(result){ console.log(result); }); console.log('after foo ');可以看到结果,after foo打印在最前面
do something异步处理
还有一个问题就是回调函数访问外部变量,看下面的示例
var http=require("http"); var redis=require("redis"); var client=redis.createClient(); var counter=0; var server=http.createServer(function(req,res){ counter++; console.log("第"+counter+"个请求 start "); client.keys("*",function(err,reply){ console.log("第"+counter+"个请求 end "); res.end("data"); }); }).listen(3000); console.info("server startup at 3000"); server.on("error",function(err){ console.err(err); });上面代码主要做的就是,当请求进来的时候,给统计器counter++,然后再查一下redis,查完redis再向浏览器发送响应res
为了使查redis这个动作尽量耗时,我在redis中加入了10w条记录,即有10w个key,执行keys *命令大约需要6、7秒
打开浏览器,开三个分页,在地址栏输入http://localhost:3000/?r=1231 (三个分页的r参数要不一样,可以避免浏览器使用缓存而不发送请求)
服务端,可以看到结果如下:
server startup at 3000 第1个请求 start 第1个请求 end 第2个请求 start 第3个请求 start 第3个请求 end 第3个请求 end
可以看到第2个请求只有start 没有end ,难道是第二个请求没有响应,但回到浏览器可以发现,三个分页均正常
而事实是第2个请求响应时,counter已经被修改成3了
这种需求在nodejs里是比较常见的
要解决也很简单,只需要使用闭包就行了
var counter=0; var server=http.createServer(function(req,res){ counter++; console.log("第"+counter+"个请求 start "); client.keys("*",function(){ var c=counter; return function(err,reply){ console.log("第"+c+"个请求 end "); res.end("data"); } }()); }).listen(3000);把请求刚进来时的counter存在var c中,每个响应都有自己相对应的c了,就不会出错了
server startup at 3000 第1个请求 start 第2个请求 start 第1个请求 end 第2个请求 end 第3个请求 start 第3个请求 end