详解Node.js串行化流程控制

串行任务:需要一个接着一个坐的任务叫做串行任务。

可以使用回调的方式让几个异步任务按顺序执行,但如果任务过多,必须组织一下,否则过多的回调嵌套会把代码搞得很乱。

为了用串行化流程控制让几个异步任务按顺序执行,需要先把这些任务按预期的执行顺序放到一个数组中,这个数组将起到队列的作用:完成一个任务后按顺序从数组中取出下一个

数组中的每个任务都是一个函数。任务完成后应该调用一个处理器函数,告诉它错误状态和结果。

为了演示如何实现串行化流程控制,我们准备做个小程序,让它从一个随机选择的RSS预定源中获取一篇文章标题和URL,并显示出来。

需要从npm存储苦衷下载两个辅助模块,在命令行中(以mac系统为例)输入以下命令:

rush:bash;"> mkdir random_story cd random_story npm install request npm install htmlparser

request模块是个简化的HTTP客户端,可以获取RSS数据。htmlparser模块能够把原始的RSS数据转换成JavaScript数据结构。

在新目录下创建一个random_story.js文件,包含以下代码

rush:js;"> var fs = require('fs'); var request = require('request'); var htmlparser = require('htmlparser'); var configFilename = './RSS_Feeds.txt'; //确保包含RSS订阅列表的文件存在 function checkForRSSFile() { fs.exists(configFilename,function(exists) { if (!exists) { return next(new Error('Missing RSS file: ' + configFilename)); } next(null,configFilename); }); } //读取并解析包含RSS订阅列表的文件 function readRSSFile(configFilename) { fs.readFile(configFilename,function(err,FeedList) { if (err) { return next(err); }
<a href="https://www.jb51.cc/tag/Feed/" target="_blank" class="keywords">Feed</a>List = <a href="https://www.jb51.cc/tag/Feed/" target="_blank" class="keywords">Feed</a>List.toString().replace(/^\s+|\s+$/g,'').split("\n");
var random = Math.floor(Math.random()*<a href="https://www.jb51.cc/tag/Feed/" target="_blank" class="keywords">Feed</a>List.length);
next(null,<a href="https://www.jb51.cc/tag/Feed/" target="_blank" class="keywords">Feed</a>List[random]);

});
}
//向预定源发送HTTP请求以获取数据
function downloadRSSFeed(FeedUrl) {
request({uri: FeedUrl},res,body) {
if (err) {
return next(err);
}
if (res.statusCode !== 200) {
return next(new Error('Abnormal response status code'));
}
next(null,body);
});
}
//解析到一个条目数组中
function parseRSSFeed(RSS) {
var handler = new htmlparser.RSSHandler();
var parser = new htmlparser.Parser(handler);
parser.parseComplete(RSS);
if (!handler.dom.items.length) {
return next(new Error('No RSS items found.'));
}
var item = handler.dom.items.shift();
console.log(item.title);
console.log(item.link);
}

var tasks = [
checkForRSSFile,readRSSFile,downloadRSSFeed,parseRSSFeed
];
function next(err,result) {
if (err) {
throw err;
}
var currentTask = tasks.shift();
if (currentTask) {
currentTask(result);
}
}
//开始执行串行化任务
next();

在试用这个程序之前,现在程序脚本所在的目录下创建一个RSS_Feeds.txt文件。这里只包含了一条预定源信息:

http://dave.smallpict.com/RSS.xml

后执行脚本:

rush:bash;"> node random_story.js

返回信息如上图。成功实现了一个串行化流程控制。

[async/await形式的串行化流程控制]

之后将源代码改写了一下,改写成ES7的async/await形式。水平有限,如有错误请指出!

function checkForRSSFile() {
return new Promise((resolve,reject) => {
fs.exists(configFilename,(exists) => {
if (!exists) {
reject(new Error('Missing RSS file: ' + configFilename));
}
resolve();
});
});
}

function readRSSFile(configFilename) {
return new Promise((resolve,reject) => {
fs.readFile(configFilename,(err,FeedList) => {
if (err) {
reject(err);
}
FeedList = FeedList.toString().replace(/^\s+|\s+$/g,'').split("\n");
let random = Math.floor(Math.random()*FeedList.length);
resolve(FeedList[random]);
});
});
}

function downloadRSSFeed(FeedUrl) {
return new Promise((resolve,reject) => {
request({uri: FeedUrl},body) => {
if (err) {
reject(err);
}
if (res.statusCode !== 200) {
reject(new Error('Abnormal response status code'));
}
resolve(body);
});
});
}

function parseRSSFeed(RSS) {
let handler = new htmlparser.RSSHandler();
let parser = new htmlparser.Parser(handler);
parser.parseComplete(RSS);
if (!handler.dom.items.length) {
throw new Error('No RSS items found.');
}
let item = handler.dom.items.shift();
console.log(item.title);
console.log(item.link);
}

async function getRSSFeed() {
await checkForRSSFile();
let url = await readRSSFile(configFilename);
let RSS = await downloadRSSFeed(url);
return RSS;
}
getRSSFeed().then(RSS => parseRSSFeed(RSS),e => console.log(e));

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持编程之家。

相关文章

这篇文章主要介绍“基于nodejs的ssh2怎么实现自动化部署”的...
本文小编为大家详细介绍“nodejs怎么实现目录不存在自动创建...
这篇“如何把nodejs数据传到前端”文章的知识点大部分人都不...
本文小编为大家详细介绍“nodejs如何实现定时删除文件”,内...
这篇文章主要讲解了“nodejs安装模块卡住不动怎么解决”,文...
今天小编给大家分享一下如何检测nodejs有没有安装成功的相关...