详解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 相关文章推荐
在IE,Firefox,Safari,Chrome,Opera浏览器上调试javascript
Dec 02 Javascript
asp.net HttpHandler实现图片防盗链
Nov 09 Javascript
十分钟打造AutoComplete自动完成效果代码
Dec 26 Javascript
JavaScript的类型转换(字符转数字 数字转字符)
Aug 30 Javascript
jQuery中$.ajax()和$.getJson()同步处理详解
Aug 12 Javascript
jQuery实现固定在网页顶部的菜单效果代码
Sep 02 Javascript
基于JavaScript代码实现随机漂浮图片广告
Jan 05 Javascript
JS及PHP代码编写八大排序算法
Jul 12 Javascript
angular.js 路由及页面传参示例
Feb 24 Javascript
vue项目常用组件和框架结构介绍
Dec 24 Javascript
JS立即执行函数功能与用法分析
Jan 15 Javascript
JS script脚本中async和defer区别详解
Jun 24 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 curl_setopt()函数实例代码与参数分析
2011/06/02 PHP
PHP文件缓存类示例分享
2015/01/30 PHP
PHP中trim()函数简单使用指南
2015/04/16 PHP
PHP内存缓存功能memcached示例
2016/10/19 PHP
PHP常见字符串操作函数与用法总结
2019/03/04 PHP
Laravel使用原生sql语句并调用的方法
2019/10/09 PHP
javascript 浏览器判断 绑定事件 arguments 转换数组 数组遍历
2009/07/06 Javascript
Jquery之美中不足小结
2011/02/16 Javascript
基于jquery的使ListNav兼容中文首字拼音排序的实现代码
2011/07/10 Javascript
幻灯片带网页设计中的20个奇妙应用示例小结
2012/05/27 Javascript
javascript实例--教你实现扑克牌洗牌功能
2014/05/15 Javascript
jQuery插件EnPlaceholder实现输入框提示文字
2015/06/05 Javascript
TypeScript 中接口详解
2015/06/19 Javascript
浅析jQuery操作select控件的取值和设值
2016/12/07 Javascript
AngularJS过滤器filter用法分析
2016/12/11 Javascript
js css自定义分页效果
2017/02/24 Javascript
jQuery实现简单弹窗遮罩效果
2017/02/27 Javascript
[58:15]2018DOTA2亚洲邀请赛 4.1 小组赛 A组 NB vs Liquid
2018/04/02 DOTA
python结合API实现即时天气信息
2016/01/19 Python
python实现linux下抓包并存库功能
2018/07/18 Python
pandas求两个表格不相交的集合方法
2018/12/08 Python
Python3从零开始搭建一个语音对话机器人的实现
2019/08/23 Python
django rest framework 自定义返回方式
2020/07/12 Python
Python打印不合法的文件名
2020/07/31 Python
意大利包包和行李箱销售网站:Bagaglio.it
2021/03/02 全球购物
Kingsoft金山公司C/C++笔试题
2016/05/10 面试题
北京某公司的.net笔试题
2014/03/20 面试题
初婚未育证明
2014/01/15 职场文书
关于爱国的演讲稿
2014/05/07 职场文书
啤酒节策划方案
2014/05/28 职场文书
医药销售自荐书
2014/05/29 职场文书
2014年人事部工作总结
2014/12/03 职场文书
个人道歉信大全
2019/04/11 职场文书
又涨知识了,自律到底多重要?
2019/06/27 职场文书
如何使用PostgreSQL进行中文全文检索
2021/05/27 PostgreSQL
MySQL分区路径子分区再分区
2022/04/13 MySQL