详解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 相关文章推荐
动态改变div的z-index属性的简单实例
Aug 08 Javascript
利用JQuery和Servlet实现跨域提交请求示例分享
Feb 12 Javascript
arguments对象验证函数的参数是否合法
Jun 26 Javascript
JS实现横向拉伸动感伸缩菜单效果代码
Sep 04 Javascript
BootStrap的JS插件之轮播效果案例详解
May 16 Javascript
浅谈jquery上下滑动的注意事项
Oct 13 Javascript
详解webpack 多页面/入口支持&公共组件单独打包
Jun 29 Javascript
JavaScript中附件预览功能实现详解(推荐)
Aug 15 Javascript
Vue中封装input组件的实例详解
Oct 17 Javascript
使用Vue生成动态表单
Nov 26 Javascript
element-ui树形控件后台返回的数据+生成组织树的工具类
Mar 05 Javascript
js+css实现扇形导航效果
Aug 18 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
IIS6的PHP最佳配置方法
2007/03/19 PHP
ThinkPHP控制器间实现相互调用的方法
2014/10/31 PHP
判断、添加和删除WordPress置顶文章的相关PHP函数小结
2015/12/10 PHP
在Laravel中使用MongoDB的方法示例
2019/11/11 PHP
prototype class详解
2006/09/07 Javascript
复制小说文本时出现的随机乱码的去除方法
2010/09/07 Javascript
修改jquery.lazyload.js实现页面延迟载入
2010/12/22 Javascript
Jquery.LazyLoad.js修正版下载,实现图片延迟加载插件
2011/03/12 Javascript
Js放到HTML文件中的哪个位置有什么区别
2013/08/21 Javascript
jQuery 复合选择器应用的几个例子
2014/09/11 Javascript
ECMAScript6块级作用域及新变量声明(let)
2015/06/12 Javascript
简介JavaScript中Math.LOG10E属性的使用
2015/06/14 Javascript
JavaScript模拟数组合并concat
2016/03/06 Javascript
vue 打包后的文件部署到express服务器上的方法
2017/08/09 Javascript
Vue响应式原理深入解析及注意事项
2017/12/11 Javascript
webpack vue项目开发环境局域网访问方法
2018/03/20 Javascript
vue.js 实现评价五角星组件的实例代码
2018/08/13 Javascript
代码分析vue中如何配置less
2018/09/28 Javascript
手动下载Chrome并解决puppeteer无法使用问题
2018/11/12 Javascript
vue axios封装及API统一管理的方法
2019/04/18 Javascript
微信小程序--获取用户地理位置名称(无须用户授权)的方法
2019/04/29 Javascript
layer.confirm点击第一个按钮关闭弹出框的方法
2019/09/09 Javascript
javascript实现点亮灯泡特效示例
2019/10/15 Javascript
Python中的列表知识点汇总
2015/04/14 Python
好的Python培训机构应该具备哪些条件
2018/05/23 Python
python实现彩票系统
2020/06/28 Python
Python全局锁中如何合理运用多线程(多进程)
2019/11/06 Python
flask 使用 flask_apscheduler 做定时循环任务的实现
2019/12/10 Python
python 安装库几种方法之cmd,anaconda,pycharm详解
2020/04/08 Python
python安装后的目录在哪里
2020/06/21 Python
django rest framework使用django-filter用法
2020/07/15 Python
python从ftp获取文件并下载到本地
2020/12/05 Python
pycharm + django跨域无提示的解决方法
2020/12/06 Python
CSS3制作圆角图片和椭圆形图片
2016/07/08 HTML / CSS
高中军训感言500字
2014/02/24 职场文书
司机职责范本
2014/03/08 职场文书