我是一个新的nodejs开发人员,我认为我理解nodejs的设计。
我可以理解一些与系统调用相关的库应该是异步的。这些作业将在不同的线程池中排队并处理,并在完成后通过回调通知。
但是,我无法理解为什么一些非系统调用相关的库使用回调作为通信方法。例如,xml2js库是用Javascript编写的,显然,这个解析函数没有理由通过回调返回状态。它可以直接返回处理结果,并且代码可读性会提高。
我的问题是,是否有任何理由让某些nodejs库设计师坚持基于回调的通信而不仅仅是使用返回值?
答案 0 :(得分:5)
回调风格没有任何问题。
var return = doSomething();
...
doSomething(function(return) {
...
});
这是首选。他们都有效。前者似乎只是“更好”,因为你已经习惯了。
后者的一个很好的理由是,当您将库更改为非阻塞时,不必更改API。
需要提醒的是,节点是一个低级非阻塞IO库。如果您要执行类似js2xml的操作,那么显然您正在等待节点0.6来标准化Web worker子流程API,这样您就可以将繁重的工作发送到子流程,并以非阻塞的方式进行实际的艰苦工作。
要以非阻塞的方式执行此操作,您的API需要是异步的(或者您需要将其构建为语言)。
答案 1 :(得分:3)
如果它不是异步的,则没有理由使用回调来传递返回值。
我见过一些使用回调而不是返回的库只是为了传回错误,但在我看来,使用throws更好更清洁。
答案 2 :(得分:1)
实际上就LibXML解析器实现而言。你确定没有系统级IO可用吗?
考虑您解析的XML包含DTD或Schema的场景。那些经常在XML-Parsers中完成的XInclude处理呢。
虽然没有根本原因,但要使用不使用任何低级IO函数的API来使用异步回调样式,您并不总是知道是否存在IO实际可能发生的情况。
现在假设您知道您的XML-Parser没有执行任何IO,因为它不处理XInclude和DTD / Schema验证。因此,如果您决定采用“传统”返回值路由,那么在不更改API的情况下,您将永远无法实现XInclude Processing或Schema验证。
通常,如果您正在编写API,那么最好从一开始就进行异步/回调,因为您永远不知道以后要做什么。
答案 3 :(得分:0)
回调在各种场景中都很有用,例如当你在迭代某些集合时(由于某种原因封装):
function Foo() {
this._data = [1, 2, 3, 4, 5];
}
Foo.prototype.forEach = function(callback) {
var i,
len = this._data.length;
for(i = 0; i < len; i++) {
callback("Item number: " + this._data[i]);
}
}
var foo = new Foo();
foo.forEach(function(item) {
console.log(item);
});