详解Node.js串行化流程控制
串行任务:需要一个接着一个坐的任务叫做串行任务。
可以使用回调的方式让几个异步任务按顺序执行,但如果任务过多,必须组织一下,否则过多的回调嵌套会把代码搞得很乱。
为了用串行化流程控制让几个异步任务按顺序执行,需要先把这些任务按预期的执行顺序放到一个数组中,这个数组将起到队列的作用:完成一个任务后按顺序从数组中取出下一个。
数组中的每个任务都是一个函数。任务完成后应该调用一个处理器函数,告诉它错误状态和结果。
为了演示如何实现串行化流程控制,我们准备做个小程序,让它从一个随机选择的rss预定源中获取一篇文章的标题和url,并显示出来。
需要从npm存储苦衷下载两个辅助模块,在命令行中(以mac系统为例)输入以下命令:
mkdir random_story cd random_story npm install request npm install htmlparser
request模块是个简化的http客户端,可以获取rss数据。htmlparser模块能够把原始的rss数据转换成javascript数据结构。
在新目录下创建一个random_story.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); } feedlist = feedlist.tostring().replace(/^\s+|\s+$/g, '').split("\n"); var random = math.floor(math.random()*feedlist.length); next(null, feedlist[random]); }); } //向预定源发送http请求以获取数据 function downloadrssfeed(feedurl) { request({uri: feedurl}, function(err, 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
之后执行脚本:
node random_story.js
返回信息如上图。成功实现了一个串行化流程控制。
[async/await形式的串行化流程控制]
之后将源代码改写了一下,改写成es7的async/await形式。水平有限,如有错误请指出!
let fs = require('fs'); let request = require('request'); let htmlparser = require('htmlparser'); let configfilename = './rss_feeds.txt'; 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}, (err, res, 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));
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
上一篇: 韭菜鸡蛋包子这样做最好吃!
下一篇: AMD矿卡真不值钱:一个月暴跌40%