源码网商城,靠谱的源码在线交易网站 我的订单 购物车 帮助

源码网商城

node.js下when.js 的异步编程实践

  • 时间:2020-12-13 03:40 编辑: 来源: 阅读:
  • 扫一扫,手机访问
摘要:node.js下when.js 的异步编程实践
假设一个业务场景: 通过rss地址,获取rss并保存于文件,rss地址保存于文件中。 完成该场景的业务需要完成3个任务: 1.从文件中读取rss地址。 2.获取rss。 3.保存于文件。 最后将这三个任务进行整合。 准备: 存放rss地址的文件,address.txt。 [url=http://programmer.csdn.net/rss_programmer.html]http://programmer.csdn.net/rss_programmer.html[/url]   任务1: 读取rss地址文件的内容并通过callback返回。
[u]复制代码[/u] 代码如下:
var getRssAddress = function(path, callback) {   fs.readFile(path, {encoding: 'utf8'}, function (err, data) {     callback(err, data);   }); }
任务2:  通过rss地址get到rss,并通过callback返回错误或数据。
[u]复制代码[/u] 代码如下:
var getRss = function(url, callback) {   var data = '';   http.get(url, function(res) {     res.on('data', function(chrunk) {       data += chrunk;     });     res.on('end', function() {       callback(null, data);     });   }).on('error', function(err) {     callback(err, null);   }); }
  任务3: 将rss保存于文件并通过callback返回错误。
[u]复制代码[/u] 代码如下:
var saveRss = function(data, callback) {   fs.writeFile('rss.txt', data, 'utf8', function(err) {     callback(err);   }); }
整合:
[u]复制代码[/u] 代码如下:
getRssAddress('address.txt', function(err, data) {   if(err) {     console.log(err);     return;   }   getRss(data, function(err, data) {     if(err) {       console.log(err);       return;     }     saveRss(data, function(err) {       if(err) console.log(err);     });   }); });
上面的代码是全异步处理,使用最常见的callback处理异步逻辑的返回,好处是标准写法,大家都能容易接受;坏处是耦合性太强,处理异常麻烦,代码不直观,特别是处理业务逻辑复杂和处理任务多的场景,层层的callback会让人眼冒金星,代码难以维护。 Promise/A规范的实现之一when.js正是针对这样的问题域。 让我们来看一下改造后的代码。 任务1:
[u]复制代码[/u] 代码如下:
var getRssAddress = function(path) {     var deferred = when.defer();       fs.readFile(path, {encoding: 'utf8'}, function (err, data) {         if (err) deferred.reject(err);         deferred.resolve(data);       });     return deferred.promise; }
  任务2:
[u]复制代码[/u] 代码如下:
var getRss = function(url) {   var deferred = when.defer();     var data = '';     http.get(url, function(res) {       res.on('data', function(chrunk) {         data += chrunk;       });       res.on('end', function() {         deferred.resolve(data);       });     }).on('error', function(err) {       deferred.reject(err);     });     return deferred.promise; }
任务3:
[u]复制代码[/u] 代码如下:
var saveRss = function(data) {   var deferred = when.defer();   fs.writeFile('rss.txt', data, 'utf8', function(err) {     if(err) deferred.reject(err);     deferred.resolve();   });   return deferred.promise; }
  整合:
[u]复制代码[/u] 代码如下:
getRssAddress('address.txt')   .then(getRss)   .then(saveRss)   .catch(function(err) {     console.log(err);   });
解释: promise/A规范定义的“Deferred/Promise”模型就是“发布/订阅者”模型,通过Deferred对象发布事件,可以是完成resolve事件,或者是失败reject事件;通过Promise对象进行对应完成或失败的订阅。 在Promises/A规范中,每个任务都有三种状态:默认(pending)、完成(fulfilled)、失败(rejected)。 1.默认状态可以单向转移到完成状态,这个过程叫resolve,对应的方法是deferred.resolve(promiseOrValue); 2.默认状态还可以单向转移到失败状态,这个过程叫reject,对应的方法是deferred.reject(reason); 3.默认状态时,还可以通过deferred.notify(update)来宣告任务执行信息,如执行进度; 4.状态的转移是一次性的,一旦任务由初始的pending转为其他状态,就会进入到下一个任务的执行过程中。 按照上面的代码。 通过when.defer定义一个deferred对象。 var deferred = when.defer(); 异步数据获取成功后,发布一个完成事件。 deferred.resolve(data); 异步数据获取失败后,发布一个失败事件。 deferred.reject(err); 并且返回Promise对象作为订阅使用。 return deferred.promise; 订阅是通过Promise对象的then方法进行完成/失败/通知的订阅。 getRssAddress('address.txt')   .then(getRss) then有三个参数,分别是onFulfilled、onRejected、onProgress promise.then(onFulfilled, onRejected, onProgress) 上一个任务被resolve(data),onFulfilled函数就会被触发,data作为它的参数. 上一个任务被reject(reason),那么onRejected就会被触发,收到reason。 任何时候,onFulfilled和onRejected都只有其一可以被触发,并且只触发一次。 对于处理异常,when.js也提供了极其方便的方法,then能传递错误,多个任务串行执行时,我们可以只在最后一个then定义onRejected。也可以在最后一个then的后面调用catch函数捕获任何一个任务的异常。 如此写法简单明了。
[u]复制代码[/u] 代码如下:
getRssAddress('address.txt')   .then(getRss)   .then(saveRss)   .catch(function(err) {     console.log(err);   });
Promise给异步编程带来了巨大的方便,可以让我们专注于单个任务的实现而不会陷入金字塔厄运,以上代码仅仅是基本使用,when.js提供的功能远远不止本文提到的这些,具体参照官方API。
  • 全部评论(0)
联系客服
客服电话:
400-000-3129
微信版

扫一扫进微信版
返回顶部