2012-08-29 25 views
1

我在问自己什么时候在node.js上使用回调进行异步处理是有意义的。 当我使用I/O,数据库以及其他所有的块或者其他代码工作时,它是否有用?Node.js何时有意义使用异步?

例如,我为棋盘游戏获得了“布局”。它使用给定的json布局创建一个电路板实例。我知道使用异步I/O(读取json布局文件)是有意义的,因为这些块。 例如使用foreach循环怎么样? 它应该是异步?底层的libuv是否从中受益?

这里是版本异步LIB:

/*jshint node: true, strict: true, globalstrict: true*/ 
"use strict"; 

// Imports 
var fs = require('fs'); 
var async = require('async'); 
var Figure = require('../models/figure.js'); 
var Field = require('../models/field.js'); 
var Board = require('../models/board.js'); 

/** 
* @param {Board} board 
* @param {Array} template 
* @param {string} owner 
* @param {function(Error)} callback 
*/ 
var createFigures = function (board, template, owner, callback) { 
    async.forEach(template, function (data, done) { 
     var figure = new Figure(owner, data.kind); 
     board.setFigure(data.x, data.y, figure); 
     done(); 
    }, callback); 
}; 

/** 
* @param {Board} board 
* @param {Array} fields 
*/ 
var createFields = function (board, fields, callback) { 
    async.series([ 
     function(done) { 
      for (var x = 0; x < board.getSize().x; x++) { 
       for (var y = 0; y < board.getSize().y; y++) { 
        var field = new Field(true, false); 
        board.setField(x, y, field); 
       } 
      } 
      done(); 
     }, function(done) { 
      async.forEach(fields, function(data, iteratDone) { 
       var field = new Field(data.passable, data.corner); 
       board.setField(data.x, data.y, field); 
       iteratDone(); 
      }); 
      done(); 
     } 
    ], callback); 
}; 

/** 
* @param {{ 
* .... 
*/ 
var build = function (layoutObj, callback) { 
    var board = new Board(layoutObj.name, layoutObj.size.x, layoutObj.size.y); 

    async.parallel([ 
     function (done) { 
      createFigures(board, layoutObj.figures.white, Figure.owners.white, done); 
     }, 
     function (done) { 
      createFigures(board, layoutObj.figures.black, Figure.owners.black, done); 
     }, 
     function (done) { 
      createFields(board, layoutObj.fields, done); 
     } 
    ], 
     function (err) { 
      callback(err, board); 
     } 
    ); 
}; 

/** 
* @param string layoutPath 
* @param {function(Error,)} callback 
* @return {Board} 
*/ 
var generateBoardWithLayout = function (layoutPath, callback) { 
    async.waterfall([ 
     function(done) { 
      fs.stat(layoutPath, function(err, stats) { 
       done(null, stats); 
      }); 
     }, function(stats, done) { 
      if (stats.isFile()) { 
       var jsonData = ''; 
       fs.readFile(layoutPath, function(err, data) { 
        jsonData += data; 
        done(null, jsonData); 
       }); 
      } else { 
       done(new Error("There is no '" + layoutPath + "'")); 
      } 
     } 
    ], function(err, jsonData) { 
     build(JSON.parse(jsonData), callback); 
    }); 

}; 

module.exports.build = build; 
module.exports.generateBoardWithLayout = generateBoardWithLayout; 

和多数民众的版本异步链路

/*jshint node: true, strict: true, globalstrict: true*/ 
"use strict"; 

// Imports 
var Figure = require('../models/figure.js'); 
var Field = require('../models/field.js'); 
var Board = require('../models/board.js'); 

/** 
* @constructor 
*/ 
function Layouter() { 

} 

Layouter.generateBoardWithLayout = function(layoutPath) { 
    var fs = require('fs'); 

    var jsonData = fs.readFileSync(layoutPath); 
    if (!jsonData) { 
     throw new Error("There is no '" + layoutPath + "'"); 
    } 

    return new Layouter().build(JSON.parse(jsonData)); 
}; 

Layouter.prototype = { 

    /** 
    * @param {{ 
    *  .... 
    */ 
    build: function (layoutObj) { 
     var board = new Board(layoutObj.name, layoutObj.size.x, layoutObj.size.y); 

     this.createFigures_(board, layoutObj.figures.white, Figure.owners.white); 
     this.createFigures_(board, layoutObj.figures.black, Figure.owners.black); 
     this.createFields_(board, layoutObj.fields); 

     return board; 
    }, 

    /** 
    * @param {Board} board 
    * @param {Array} template 
    * @param {string} owner 
    * @private 
    */ 
    createFigures_: function (board, template, owner) { 
     template.forEach(function (data) { 
      var figure = new Figure(owner, data.kind); 
      board.setFigure(data.x, data.y, figure); 
     }); 
    }, 

    /** 
    * @param {Board} board 
    * @param {Array} fields 
    * @private 
    */ 
    createFields_: function (board, fields) { 
     for (var x = 0; x < board.getSize().x; x++) { 
      for (var y = 0; y < board.getSize().y; y++) { 
       var field = new Field(true, false); 
       board.setField(x, y, field); 
      } 
     } 

     fields.forEach(function (data) { 
      var field = new Field(data.passable, data.corner); 
      board.setField(data.x, data.y, field); 
     }); 
    } 

}; 

module.exports = Layouter; 
module.exports.generateBoardWithLayout = Layouter.generateBoardWithLayout; 

感谢您的时间!

问候, 马库斯

+0

这个问题应该包含在异步IO背后的基金会。只需使用谷歌 –

+0

小gfx比长篇演讲要好:https://developers.google.com/appengine/docs/python/ndb/guestbook_sync_vs_async.png –

回答

0

我想你错过了在Node.js异步性背后的想法。这不是关于使用async包(它只是可用于Node的npm包,而不是Node的内部包),而不是以异步方式处理外部进程。例如当你查询数据库时,你可能会在等待结果的同时做很多事情,那就是交易。

如果你的代码没有查询任何外部进程,但它是普通的JavaScript,那么单个进程不能直接受益于异步(Node.js是单线程的),然而你可能做的是委派一些工作到不同的进程并与之通信(请参阅child_process.fork)。

0

看起来像你刚刚作出新的对象实例,而不做任何I/O,在这种情况下,u的代码不必要地复杂,这是丑陋的。您只能在最后一次回调函数中继续执行程序,这会将整个流程限制为一次大的异步调用。

通常你的程序流程不应该依赖于以前的异步回调先EXCUTE,在你的代码

createFigure(); 
createField(); 

两者都在一个异步调用,如果有什么东西在createField取决于createFigure首先要excuted,在这种情况下,行为是不确定的。一般来说,不要使用异步,除非你正在做阻塞操作

+0

好的,那就是我的想法。谢谢! – stahlstift