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

前端之家收集整理的这篇文章主要介绍了node.js下when.js 的异步编程实践前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

假设一个业务场景:

通过RSS地址,获取RSS并保存于文件RSS地址保存于文件中。

完成该场景的业务需要完成3个任务:

1.从文件中读取RSS地址。

2.获取RSS

3.保存于文件

最后将这三个任务进行整合。

准备:

存放RSS地址的文件,address.txt。

任务1:

读取rss地址文件的内容并通过callback返回。

代码如下:
RSSAddress = function(path,callback) { fs.readFile(path,{encoding: 'utf8'},function (err,data) { callback(err,data); }); }

任务2:

通过RSS地址get到RSS,并通过callback返回错误或数据。

代码如下:
RSS = 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返回错误

代码如下:
5026"> var saveRSS = function(data,callback) { fs.writeFile('RSS.txt',data,'utf8',function(err) { callback(err); }); }

整合:

代码如下:
RSSAddress('address.txt',function(err,data) { if(err) { console.log(err); return; } getRSS(data,data) { if(err) { console.log(err); return; } saveRSS(data,function(err) { if(err) console.log(err); }); }); });

上面的代码是全异步处理,使用最常见的callback处理异步逻辑的返回,好处是标准写法,大家都能容易接受;坏处是耦合性太强,处理异常麻烦,代码不直观,特别是处理业务逻辑复杂和处理任务多的场景,层层的callback会让人眼冒金星,代码难以维护。

Promise/A规范的实现之一when.js正是针对这样的问题域。

让我们来看一下改造后的代码

任务1:

代码如下:
RSSAddress = function(path) { var deferred = when.defer(); fs.readFile(path,data) { if (err) deferred.reject(err); deferred.resolve(data); });

return deferred.promise; }

任务2:

代码如下:
RSS = function(url) { var deferred = when.defer(); var data = ''; http.get(url,function() { deferred.resolve(data); }); }).on('error',function(err) { deferred.reject(err); });

return deferred.promise; }

任务3:

代码如下:
RSS = function(data) { var deferred = when.defer(); fs.writeFile('RSS.txt',function(err) { if(err) deferred.reject(err); deferred.resolve(); });

return deferred.promise; }

整合:

代码如下:
RSSAddress('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函数捕获任何一个任务的异常。

如此写法简单明了。

代码如下:
RSSAddress('address.txt') .then(getRSS) .then(saveRSS) .catch(function(err) { console.log(err); });

Promise给异步编程带来了巨大的方便,可以让我们专注于单个任务的实现而不会陷入金字塔厄运,以上代码仅仅是基本使用,when.js提供的功能远远不止本文提到的这些,具体参照官方API。

猜你在找的Node.js相关文章