详解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 相关文章推荐
学习YUI.Ext基础第一天
Mar 10 Javascript
Js 本页面传值实现代码
May 17 Javascript
一些经常会用到的Javascript检测函数
May 31 Javascript
通过JS来动态的修改url,实现对url的增删查改
Sep 01 Javascript
浅谈javascript中this在事件中的应用
Feb 15 Javascript
JavaScript获取当前url根目录(路径)
Jun 17 Javascript
indexedDB bootstrap angularjs之 MVC DOMO (应用示例)
Jun 20 Javascript
jquery实现楼层滚动效果
Jan 01 jQuery
基于jQuery实现无缝轮播与左右点击效果
May 13 jQuery
jQuery实现鼠标滑动切换图片
May 27 jQuery
小程序实现侧滑删除功能
Jun 25 Javascript
canvas 中如何实现物体的框选
Aug 05 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
超神学院:鹤熙已踏入神圣领域,实力不比凯莎弱
2020/03/02 国漫
微信公众号开发之语音消息识别php代码
2016/08/08 PHP
Zend Framework框架中实现Ajax的方法示例
2017/06/27 PHP
javascript 三种编解码方式
2010/02/01 Javascript
JavaScript OOP面向对象介绍
2010/12/02 Javascript
node.js中Socket.IO的进阶使用技巧
2014/11/04 Javascript
JavaScript更改原始对象valueOf的方法
2015/03/19 Javascript
js动态修改表格行colspan列跨度的方法
2015/03/30 Javascript
JavaScript中的getTimezoneOffset()方法使用详解
2015/06/10 Javascript
jQuery实现移动端手机商城购物车功能
2016/09/24 Javascript
简单模拟node.js中require的加载机制
2016/10/27 Javascript
获取select的value、text值的简单示例(jquery与javascript)
2016/12/07 Javascript
详解webpack+express多页站点开发
2017/12/22 Javascript
微信小程序实现流程进度的图样式功能
2018/01/16 Javascript
关于redux-saga中take使用方法详解
2018/02/27 Javascript
vue.js给动态绑定的radio列表做批量编辑的方法
2018/02/28 Javascript
JavaScript事件发布/订阅模式原理与用法分析
2018/08/21 Javascript
详解Vue-cli3 项目在安卓低版本系统和IE上白屏问题解决
2019/04/14 Javascript
Nodejs + sequelize 实现增删改查操作
2020/11/07 NodeJs
跟老齐学Python之字典,你还记得吗?
2014/09/20 Python
Python多维/嵌套字典数据无限遍历的实现
2016/11/04 Python
python matplotlib画图库学习绘制常用的图
2019/03/19 Python
python根据文本生成词云图代码实例
2019/11/15 Python
kafka监控获取指定topic的消息总量示例
2019/12/23 Python
Pandas将列表(List)转换为数据框(Dataframe)
2020/04/24 Python
keras绘制acc和loss曲线图实例
2020/06/15 Python
PyTorch之nn.ReLU与F.ReLU的区别介绍
2020/06/27 Python
如何使用python记录室友的抖音在线时间
2020/06/29 Python
python 使用多线程创建一个Buffer缓存器的实现思路
2020/07/02 Python
python 爬虫如何实现百度翻译
2020/11/16 Python
美国最大的在线寄售和旧货店:Swap.com
2018/08/27 全球购物
英国首屈一指的票务公司:See Tickets
2019/05/11 全球购物
维氏瑞士军刀英国网站:Victorinox英国
2019/07/04 全球购物
Java里面有没有全局变量?为什么?
2015/02/06 面试题
司机岗位职责说明书
2014/07/29 职场文书
golang elasticsearch Client的使用详解
2021/05/05 Golang