我对node.js的异步性质感到困惑。我正在写一个小项目,我以前的(同步)编程经验会受到影响。
我应该如何判断是否/在哪里编写异步代码?
例如,我有一个带字段的模型,每个字段都有一些验证规则:
model = { title: text_validation,
subtitle: text_validation }
text_validation = { max_len: 10,
required: true,
url: true }
当我验证模型时,我会遍历所有字段,检查规则是否通过 - 这些都是非常快速的功能。
Model.validate = function() {
validator = {};
fields = Object.keys(Model);
fields.forEach(function(field) {
validator[field_name] = field.validate();
});
}
Field.validate = function() {
validator = [];
rules.forEach(function(rule) {
if (rule is not valid)
validator.push(rule)
});
return validator;
}
我应该使用如此短而快速的迭代回调吗?
这里的限制在哪里? node.js应该始终是异步还是我可以允许同步循环或w / e如果它足够快?如果可能,请参考示例何时何地使用sync / async。
答案 0 :(得分:6)
你可能不应该。在大多数情况下,只有在等待应用程序外部的某些内容(主要是文件,数据库和网络操作)时,才需要异步逻辑。异步延迟应用程序内代码将不会给您带来任何性能优势,因为您的代码仍然需要在某个时间运行 。
答案 1 :(得分:2)
我已在评论中说过,但我认为提供示例也是一个好主意。
回调和 asynchrounous操作的概念虽然相关,但却不同。您使用的forEach
循环根本不是异步。以下是forEach
的定义或多或少的样子:
Array.prototype.forEach = function(callback) {
var l = this.length;
for (var i = 0; i < l; i++)
callback(this[i], i);
};
正如您所看到的,这里没有任何异步。 callback
在步骤之后的循环步骤中同步执行。
那么如何使循环异步?好吧,你可以试试这个:
Array.prototype.asyncForEach = function(applier, finished) {
var self = this;
var l = self.length;
var call = function(i) {
process.nextTick(function() {
applier(self[i], i);
if (i == l-1)
finished();
else
call(i+1);
});
}
call(0);
};
你可以像这样使用它:
var x = [1,2,3,4,5,6,7,8,9,10];
x.asyncForEach(function(el, index) {
/* apply function to each el and index */
console.log(el);
}, function() {
/* This will be called when the loop finishes! */
console.log('Finished!');
});
/* Let us check whether the loop is really asynchronous.
The following code should fire BEFORE loop! */
console.log('Is it asynchronous?');
正如您所看到的,它不像forEach
那么容易和简单。但这允许其他代码在循环的迭代之间运行(process.nextTick
方法的魔力)。所以你获得High Availability,但成本是循环完成所需的时间更长。请注意,可以在迭代之间修改数组,这可能会导致应用程序崩溃。 :d
正如我在评论中所说的:我从来没有见过循环工作这么长时间以至于它实际上需要转向异步循环。我已经处理了一些我处理过的市场数据(尽管使用Python,而不是JavaScript - 这可能是一个原因)。正如lanzz评论的那样,如果循环花费太多时间,那么分叉可能是一个好主意。或者创建一个用某种有效语言(C?)编写的WebService(或Node.JS addon)。