详解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判断代码
Mar 13 Javascript
用js实现判断当前网址的来路如果不是指定的来路就跳转到指定页面
May 02 Javascript
通过jquery的$.getJSON做一个跨域ajax请求试验
May 03 Javascript
基于ajax实现文件上传并显示进度条
Aug 03 Javascript
js实现仿MSN带关闭功能的右下角弹窗代码
Sep 04 Javascript
AngularJS中实现显示或隐藏动画效果的方式总结
Dec 31 Javascript
Node.js重新刷新session过期时间的方法
Feb 04 Javascript
JS学习之表格的排序简单实例
May 16 Javascript
js实现城市级联菜单的2种方法
Jun 23 Javascript
jquery获取select选中值的文本,并赋值给另一个输入框的方法
Aug 21 jQuery
Angular实现svg和png图片下载实现
May 05 Javascript
Vue实现Header渐隐渐现效果的实例代码
Nov 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
第七节 类的静态成员 [7]
2006/10/09 PHP
php 无法加载mysql的module的时候的配置的解决方案引发的思考
2012/01/27 PHP
解析Ubuntu下crontab命令的用法
2013/06/24 PHP
PHPAnalysis中文分词类详解
2014/06/13 PHP
如何解决phpmyadmin导入数据库文件最大限制2048KB
2015/10/09 PHP
php读取XML的常见方法实例总结
2017/04/25 PHP
js几个验证函数代码
2010/03/25 Javascript
对xmlHttp对象的理解
2011/01/17 Javascript
详解强大的jQuery选择器之基本选择器、层次选择器
2012/02/07 Javascript
JavaScript中使用构造器创建对象无需new的情况说明
2012/03/01 Javascript
jquery实现可旋转可拖拽的文字效果代码
2016/01/27 Javascript
AngularJS基础 ng-mouseleave 指令详解
2016/08/02 Javascript
Javascript动画效果(2)
2016/10/11 Javascript
bootstrap multiselect 多选功能实现方法
2017/06/05 Javascript
mui 打开新窗口的方式总结及注意事项
2017/08/20 Javascript
Angular 4.0学习教程之架构详解
2017/09/12 Javascript
Vue插值、表达式、分隔符、指令知识小结
2018/10/12 Javascript
JavaScript 实现同时选取多个时间段的方法
2019/10/17 Javascript
vue实现PC端分辨率适配操作
2020/08/03 Javascript
JavaScript实现单点登录的示例
2020/09/23 Javascript
[00:12]DAC2018 no[o]ne亮相SOLO赛 他是否如他的id一样无人可挡?
2018/04/06 DOTA
[02:21]十步杀一人,千里不留行——DOTA2全新英雄天涯墨客展示
2018/08/29 DOTA
django DRF图片路径问题的解决方法
2018/09/10 Python
Python爬虫常用库的安装及其环境配置
2018/09/19 Python
python批量识别图片指定区域文字内容
2019/04/30 Python
在python中使用nohup命令说明
2020/04/16 Python
CSS3为背景图设置遮罩并解决遮罩样式继承问题
2020/06/22 HTML / CSS
Travelstart沙特阿拉伯:廉价航班、豪华酒店和实惠的汽车租赁优惠
2019/04/06 全球购物
linux比较文件内容的命令是什么
2013/03/04 面试题
毕业证丢失证明
2014/01/15 职场文书
优秀教导主任事迹材料
2014/05/09 职场文书
母亲节感言
2015/08/03 职场文书
高效课堂教学反思
2016/02/24 职场文书
Pytorch 如何实现LSTM时间序列预测
2021/05/17 Python
vue-cropper组件实现图片切割上传
2021/05/27 Vue.js
MyBatis-Plus 批量插入数据的操作方法
2021/09/25 Java/Android