在初学者教程中,Node的非阻塞性质通常通过显示阻塞示例(使用return
语句)和非阻塞节点示例(使用回调)来演示。有关示例,请参阅here。
我是否应该将其视为“气味”,使用return
在我的Node应用中创建阻止代码,并找到使用回调重做它的方法?
答案 0 :(得分:4)
TL; DR:如果代码可能花费很长时间,可能更清洁/更有效率地通过回调来处理它。
这不是关于返回/不返回,而是关于代码实际执行的操作。
示例函数不会阻止,因为有一个返回,它会阻塞,因为db.query
需要任意的时间。如果您想在此期间执行其他操作,请立即返回,并在回调中执行结果处理。
p>
答案 1 :(得分:1)
阻止调用通常会返回一些内容,因为返回发生在调用引起的“操作”之后,因此它可以返回有关操作成功或失败的信息,以及操作产生的任何数据。这也适用于不会阻塞本身但不执行i / o的调用,因此不需要回调。
非阻塞调用,例如读取文件的函数,不倾向于使用返回值,因为它们通常在执行任何重要操作之前返回。相反,他们调用回调并发送它产生的任何数据,或者可能是错误消息。
答案 2 :(得分:0)
使用非阻塞调用的主要动机是您正在等待某些外部进程或设备返回,因此您释放对该线程的控制权以允许其他操作在“等待时”运行。
因为使用回调的非阻塞/异步代码更难以编写,读取和维护,所以应避免使用非阻塞代码,除非它会对应用程序的性能和可伸缩性产生影响,或者需要它通过您正在使用的API。
考虑这个相对愚蠢的例子:
function add(a,b,cb) { cb(a+b); }
console.log('2+2 is', add(2,2)); // -> 4
function add(a,b) { return a+b; }
add(2,2,function(sum) { console.log('2+2 is', sum); }); // -> 4
第一个在眼睛上更容易。
许多节点API具有异步版本但没有同步版本。使用这些API时,显然需要使代码异步。
如果您有选择(如同阅读文件时),请问自己:“阻止呼叫是否会使最终用户等待不合理的时间?”。在应用程序启动期间,答案通常是“否”,因为该代码仅运行一次,最终用户没有机会触摸服务器。但是,如果您正在响应Web请求,那么让所有用户等待出站API调用或磁盘读取将使所有用户的站点变慢,而非阻塞调用允许节点继续处理新请求,直到数据为您请求回来。