详解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 相关文章推荐
jQuery队列控制方法详解queue()/dequeue()/clearQueue()
Dec 02 Javascript
iframe 上下滚动条如何默认在下方实现原理
Dec 10 Javascript
jQuery页面图片伴随滚动条逐渐显示的小例子
Mar 21 Javascript
如何使用jQUery获取选中radio对应的值(一句代码)
Jun 03 Javascript
jQuery.ajax 跨域请求webapi设置headers的解决方案
Aug 08 Javascript
Bootstrap轮播图的使用和理解4
Dec 14 Javascript
React-Native左右联动List的示例代码
Sep 21 Javascript
Vue中对比scoped css和css module的区别
May 17 Javascript
element-ui 中的table的列隐藏问题解决
Aug 24 Javascript
js实现中文实时时钟
Jan 15 Javascript
微信小程序上传帖子的实例代码(含有文字图片的微信验证)
Jul 11 Javascript
小程序实现列表倒计时功能
Jan 29 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输出echo、print、print_r、printf、sprintf、var_dump的区别比较
2013/06/21 PHP
简单实用的网站PHP缓存类实例
2014/07/18 PHP
详解Grunt插件之LiveReload实现页面自动刷新(两种方案)
2015/07/31 PHP
php中str_pad()函数用法分析
2017/03/28 PHP
PHP检查网站是否宕机的方法示例
2017/07/24 PHP
PHP模型Model类封装数据库操作示例
2019/03/14 PHP
jquery easyui使用心得
2014/07/07 Javascript
JavaScript数组前面插入元素的方法
2015/04/06 Javascript
使用JavaScript实现连续滚动字幕效果的方法
2015/07/07 Javascript
学习javascript的闭包,原型,和匿名函数之旅
2015/10/18 Javascript
JS多物体实现缓冲运动效果示例
2016/12/20 Javascript
js移动端事件基础及常用事件库详解
2017/08/15 Javascript
angularJs中json数据转换与本地存储的实例
2018/10/08 Javascript
layer实现弹出层自动调节位置
2019/09/05 Javascript
使用Vue调取接口,并渲染数据的示例代码
2019/10/28 Javascript
Python多线程编程(五):死锁的形成
2015/04/05 Python
玩转python爬虫之正则表达式
2016/02/17 Python
python通过cookie模拟已登录状态的初步研究
2016/11/09 Python
python实现远程通过网络邮件控制计算机重启或关机
2018/02/22 Python
对numpy和pandas中数组的合并和拆分详解
2018/04/11 Python
用Python下载一个网页保存为本地的HTML文件实例
2018/05/21 Python
Python3实现定时任务的四种方式
2019/06/03 Python
详解Python3之数据指纹MD5校验与对比
2019/06/11 Python
将python依赖包打包成window下可执行文件bat方式
2019/12/26 Python
如何使用amaze ui的分页样式封装一个通用的JS分页控件
2020/08/21 HTML / CSS
HTML5中外部浏览器唤起微信分享功能的代码
2020/09/15 HTML / CSS
德国运动鞋网上商店:Afew Store
2018/01/05 全球购物
全球最大的瓷器、水晶和银器零售商:Replacements
2020/06/15 全球购物
美术教师岗位职责
2014/03/18 职场文书
解放思想大讨论活动心得体会
2014/09/11 职场文书
教师见习报告范文
2014/11/03 职场文书
2015年学校总务处工作总结
2015/05/19 职场文书
Python实现学生管理系统并生成exe可执行文件详解流程
2022/01/22 Python
Python+Selenium实现读取网易邮箱验证码
2022/03/13 Python
vue3引入highlight.js进行代码高亮的方法实例
2022/04/08 Vue.js
vue使用element-ui按需引入
2022/05/20 Vue.js