Node.js的Error-first回调模式

  如果说Google的V8引擎是Node.js的心脏,那么回调则是Node的脉络,回调能够激活跨模块和应用程序之间平衡的、非堵塞的异步控制流程,因此,在实际编写时,我们需要一个通用的可依赖的回调编程方式,error-first回调,也称为errorback或errback或node-style callback,它们都是用来解决这个问题。

  node这种高度依赖回调数据的编程风格要早于Javascript语言本身,Continuation-Passing Style (CPS)是对今天Node.js这种回调用法的古老学术用语,在CPS中, 一个"持续函数"(称为 回调)是被作为参数传入,然后再被其他代码调用运行,这就允许不同函数跨整个应用滞后或提前地进行异步处理控制。

  Node.js依赖异步代码保存快速性能,这样也就依赖回调模式,回调使用得太多会陷入嵌套回调,回调里嵌套回调,变得非常复杂,程序代码难于阅读,整个应用的流程迷失在嵌套回调中,error-first模式导入解决这个问题。

  error-first回调有两条定义规则:

  1. 1.回调函数的第一个参数保留给一个错误error对象,如果有错误发生,错误将通过第一个参数err返回。
  2. 2.回调函数的第二个参数为成功响应的数据保留,如果没有错误发生,err将被设置为null, 成功的数据将从第二个参数返回。

  下面以fs.readFile()为例子说明:

fs.readFile('/foo.txt',  function(err,  data)  { 
   // TODO: Error Handling Still Needed!
        console.log(data); 
}); 
  

  fs.readFile()从一个文件路径读取文件,一旦完成调用你的回调函数,如果一切正常 ,文件内容将被在data参数中返回,但是如果有错误发生,比如文件不存在或权限不允许,第一个err参数将会包含出错的信息。

至于错误处理这是由开发人员自己处理。

  当一个函数传递错误给回调函数,它就不管这些错误是如何处理,readFile函数不知道读取文件会出现怎样的错误,但是它可以预期,否则就会有灾难后果,但是取代自己处理错误,readFile()会传播错误回到你的原始提交处理者。

  当你遵循这种一致的模式时,错误能够如你所愿被一层层传播,每个回调能选择忽略或处理,或基于错误信息再传播。

if(err) {

  // Handle "Not Found" by responding with a custom error page

  if(err.fileNotFound) {

    return this.sendErrorMessage('File Does not Exist');

  }

  // Ignore "No Permission" errors, this controller knows that we don't care

  // Propagate all other errors (Express will catch them)

  if(!err.noPermission) {

    return next(err);

  }

}

  当有这种坚固的回调协议在心中,你就再也不会局限于一次只能使用一个回调,回调能够在队列或并行被调用或串行化方式,如果你要读取10种不同的文件,或进行100个不同的API调用,再也没有理由说不可以一次性进行了。

   async库是一种高级回调应用包,因为有error-first回调模式,它就很容易被使用:

// Example taken from caolan/async README 
async.parallel({ 
     one:  function(callback){ 
         setTimeout(function(){ 
             callback(null,  1); 
         },  200); 
     }, 
     two:  function(callback){ 
         setTimeout(function(){ 
             callback(null,  2); 
         },  100); 
     } 
}, 
function(err,  results)  {
           // results is equal to: {one: 1, two: 2} 
});

   当然其他还有Promise等方式。

NodeJS的Promise的用法

Node.js教程系列

Node.js编程之道