[英]Node.js when it makes sense to use async?
我问自己,什么时候应该与node.js上的回调异步。 当我使用I / O,数据库以及其他所有受阻的内容时还是在我的其余代码中有用吗?
例如,我得到了一个棋盘游戏的“布局”。 它使用给定的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;
谢谢你的时间!
问候,马库斯
看起来您只是在不执行任何I / O的情况下创建了新的对象实例,在这种情况下,您不必要地使代码复杂化,这很丑陋。 您只能在最后一个回调函数中继续执行程序,该函数将整个流程限制为一个大的异步调用。
通常,在您的代码中,程序流不应该依赖于先前的异步回调来首先执行
createFigure();
createField();
两者都是一个单一的异步调用,如果createField中的某些内容首先依赖于createFigure,在这种情况下,行为是不确定的,该怎么办。 通常,除非正在执行阻塞操作,否则不要使用异步
我认为您错过了Node.js中异步性的想法。 这与使用async
包(不是可以与Node一起使用的npm包,而不是Node的内部包)有关,而是与异步处理外部进程有关。 例如,当您查询数据库时,您可能会在等待结果的同时做很多事情,这很重要。
如果您的代码没有查询任何外部进程,而是纯JavaScript,那么使用单进程您将无法直接从异步中受益(Node.js是单线程的),但是您可以做的是将一些工作委派给不同的进程,并且与之通信(请参阅child_process.fork)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.