详解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 相关文章推荐
对采用动态原型方式无法展示继承机制得思考
Dec 04 Javascript
js日期时间补零的小例子
Mar 05 Javascript
js 判断文件类型并控制表单提交示例代码
Nov 14 Javascript
jquery鼠标停止移动事件
Dec 21 Javascript
JS数组合并push与concat区别分析
Dec 17 Javascript
Node.js模块封装及使用方法
Mar 06 Javascript
angular $watch 一个变量的变化(实例讲解)
Aug 02 Javascript
Vue.js移动端左滑删除组件的实现代码
Sep 08 Javascript
Vue中$refs的用法详解
Jun 24 Javascript
JS面向对象实现飞机大战
Aug 26 Javascript
vue实现简单加法计算器
Oct 22 Javascript
antd配置config-overrides.js文件的操作
Oct 31 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
header跳转和include包含问题详解
2012/09/08 PHP
PHP中Memcache操作类及用法实例
2014/12/12 PHP
PHP实现数据四舍五入的方法小结【4种方法】
2019/03/27 PHP
php+js实现的无刷新下载文件功能示例
2019/08/23 PHP
php实例化一个类的具体方法
2019/09/19 PHP
PHP7 其他修改
2021/03/09 PHP
jquery 查找select ,并触发事件的实现代码
2011/03/30 Javascript
jquery 操作DOM案例代码分享
2012/04/05 Javascript
JS正则中的RegExp对象对象
2012/11/07 Javascript
javascript实现TreeView 无刷新展开的实例代码
2013/07/13 Javascript
JS delegate与live浅析
2013/12/21 Javascript
JS 新增Cookie 取cookie值 删除cookie 举例详解
2014/10/10 Javascript
使用coffeescript编写node.js项目的方法汇总
2015/08/05 Javascript
利用JavaScript阻止表单提交的两种方法
2016/08/11 Javascript
微信小程序实现保存图片到相册功能
2018/11/30 Javascript
基于javascript canvas实现五子棋游戏
2020/07/08 Javascript
python3使用tkinter实现ui界面简单实例
2014/01/10 Python
Python3实现从文件中读取指定行的方法
2015/05/22 Python
python中Apriori算法实现讲解
2017/12/10 Python
Python 25行代码实现的RSA算法详解
2018/04/10 Python
Python爬取成语接龙类网站
2018/10/19 Python
Python中三元表达式的几种写法介绍
2019/03/04 Python
python实现键盘输入的实操方法
2019/07/16 Python
详解将Python程序(.py)转换为Windows可执行文件(.exe)
2019/07/19 Python
python+selenium select下拉选择框定位处理方法
2019/08/24 Python
Html5游戏开发之乒乓Ping Pong游戏示例(二)
2013/01/21 HTML / CSS
static全局变量与普通的全局变量有什么区别?static局部变量和普通局部变量有什么区别?static函数与普通函数有什么区别?
2015/02/22 面试题
力学专业毕业生自荐信
2013/11/17 职场文书
市场营销专业大学生职业生涯规划文
2014/03/06 职场文书
金融学专业大学生职业生涯规划
2014/03/07 职场文书
上课迟到检讨书300字
2014/10/15 职场文书
庆元旦主持词
2015/07/06 职场文书
整脏治乱工作简报
2015/07/21 职场文书
2016党员学习《反对自由主义》心得体会
2016/01/22 职场文书
攻击最高的10只幽灵系神奇宝贝,坚盾剑怪排第一,第五最为可怕
2022/03/18 日漫
javascript进阶篇深拷贝实现的四种方式
2022/07/07 Javascript