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


Posted in Javascript onMay 04, 2017

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

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

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

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

为了演示如何实现串行化流程控制,我们准备做个小程序,让它从一个随机选择的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

详解Node.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));

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
Javascript 构造函数,公有,私有特权和静态成员定义方法
Nov 30 Javascript
深入理解JavaScript系列(3) 全面解析Module模式
Jan 15 Javascript
浏览器加载、渲染和解析过程黑箱简析
Nov 29 Javascript
js获取窗口相对于屏幕左边和上边的位置坐标
May 15 Javascript
JS实现的4种数字千位符格式化方法分享
Mar 02 Javascript
纯javascript实现的小游戏《Flappy Pig》实例
Jul 27 Javascript
JS模拟并美化的表单控件完整实例
Aug 19 Javascript
TypeScript入门-基本数据类型
Mar 28 Javascript
vue-content-loader内容加载器的使用方法
Aug 05 Javascript
vue项目使用.env文件配置全局环境变量的方法
Oct 24 Javascript
webpack常用配置总览(小结)
Nov 18 Javascript
Vue组件通信$attrs、$listeners实现原理解析
Sep 03 Javascript
纯原生js实现贪吃蛇游戏
Apr 16 #Javascript
js调用刷新界面的几种方式
May 03 #Javascript
JavaScript中双向数据绑定详解
May 03 #Javascript
Js实现中国公民身份证号码有效性验证实例代码
May 03 #Javascript
Vue原理剖析 实现双向绑定MVVM
May 03 #Javascript
利用node.js写一个爬取知乎妹纸图的小爬虫
May 03 #Javascript
Vue实现双向数据绑定
May 03 #Javascript
You might like
PHP 超链接 抓取实现代码
2009/06/29 PHP
提示Trying to clone an uncloneable object of class Imagic的解决
2011/10/27 PHP
thinkPHP导出csv文件及用表格输出excel的方法
2015/12/30 PHP
理解php依赖注入和控制反转
2016/05/11 PHP
PHP连接SQL Server的方法分析【基于thinkPHP5.1框架】
2019/05/06 PHP
javascript 特性检测并非浏览器检测
2010/01/15 Javascript
CSS(js)限制页面显示的文本字符长度
2012/12/27 Javascript
悬浮数字的实现案例
2014/02/19 Javascript
javascript中字符串拼接详解
2014/09/26 Javascript
JS实现屏蔽shift,Ctrl,alt等功能键的方法
2015/06/01 Javascript
jQuery实现的文字hover颜色渐变效果实例
2016/02/20 Javascript
如何用JS判断两个数字的大小
2016/07/21 Javascript
angularJS Provider、factory、service详解及实例代码
2016/09/21 Javascript
AngulerJS学习之按需动态加载文件
2017/02/13 Javascript
angular.js指令中transclude选项及ng-transclude指令详解
2017/05/24 Javascript
基于layui数据表格以及传数据的方式
2018/08/19 Javascript
vue-vuex中使用commit提交mutation来修改state的方法详解
2018/09/16 Javascript
vue组件内部引入外部js文件的方法
2020/01/18 Javascript
解决vant中 tab栏遇到的坑 van-tabs
2020/11/04 Javascript
浅析JavaScript中的事件委托机制跟深浅拷贝
2021/01/20 Javascript
[03:56]DOTA2完美大师赛趣味视频之小鸽子和Mineski打台球
2017/11/24 DOTA
浅谈python中的数字类型与处理工具
2017/08/02 Python
Python自定义线程池实现方法分析
2018/02/07 Python
sublime python3 输入换行不结束的方法
2018/04/19 Python
python使用turtle库绘制树
2018/06/25 Python
python使用zip将list转为json的方法
2018/12/31 Python
浅谈python requests 的put, post 请求参数的问题
2019/01/02 Python
python 基于opencv实现高斯平滑
2020/12/18 Python
瑞典在互联网上最大的宠物商店:Animail
2020/10/31 全球购物
应届毕业生求职自荐书
2014/01/03 职场文书
婚前协议书范本
2014/04/15 职场文书
鉴定评语大全
2014/05/05 职场文书
银行求职信范文
2014/05/26 职场文书
基于go interface{}==nil 的几种坑及原理分析
2021/04/24 Golang
教你利用Selenium+python自动化来解决pip使用异常
2021/05/20 Python
Tomcat弱口令复现及利用
2022/05/06 Servers