详解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 相关文章推荐
JavaScript mapreduce工作原理简析
Nov 25 Javascript
关于js里的this关键字的理解
Aug 17 Javascript
Jquery获取radio选中的值
May 05 jQuery
详解基于vue-router的动态权限控制实现方案
Sep 28 Javascript
js 开发之autocomplete="off"在chrom中失效的解决办法
Sep 28 Javascript
js中bool值的转换及“&&”、“||”、 “!!”详解
Dec 21 Javascript
几个你不知道的技巧助你写出更优雅的vue.js代码
Jun 11 Javascript
记一次vue-webpack项目优化实践详解
Feb 17 Javascript
Bootstarp在pycharm中的安装及简单的使用方法
Apr 19 Javascript
发布订阅模式在vue中的实际运用实例详解
Jun 09 Javascript
浅析js实现网页截图的两种方式
Nov 01 Javascript
JSONP 的原理、理解 与 实例分析
May 16 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
laravel项目利用twemproxy部署redis集群的完整步骤
2018/05/11 PHP
javascript jQuery $.post $.ajax用法
2008/07/09 Javascript
javascript globalStorage类代码
2009/06/04 Javascript
基于jquery跨浏览器显示的file上传控件
2011/10/24 Javascript
基于jQuery的图片左右无缝滚动插件
2012/05/23 Javascript
javascript学习笔记(九) js对象 设计模式
2012/06/19 Javascript
深入了解javascript中的prototype与继承
2013/04/14 Javascript
让页面上两个div中的滚动条(滑块)同步运动示例
2013/08/07 Javascript
jquery获取form表单input元素值的简单实例
2016/05/30 Javascript
bootstrapfileinput实现文件自动上传
2016/11/08 Javascript
解析微信JS-SDK配置授权,实现分享接口
2016/12/09 Javascript
jQuery实现鼠标悬停3d菜单展开动画效果
2017/01/19 Javascript
深入理解在JS中通过四种设置事件处理程序的方法
2017/03/02 Javascript
JS自动生成动态HTML验证码页面
2017/06/14 Javascript
Angular.js组件之input mask对input输入进行格式化详解
2017/07/10 Javascript
基于vue实现网站前台的权限管理(前后端分离实践)
2018/01/13 Javascript
WebSocket的通信过程与实现方法详解
2018/04/29 Javascript
Vue使用NProgress进度条的方法
2019/09/21 Javascript
在vue-cli3中使用axios获取本地json操作
2020/07/30 Javascript
解决Vue-cli无法编译es6的问题
2020/10/30 Javascript
深入解析Python中函数的参数与作用域
2016/03/20 Python
详解TensorFlow查看ckpt中变量的几种方法
2018/06/19 Python
浅谈opencv自动光学检测、目标分割和检测(连通区域和findContours)
2020/06/04 Python
可自定义箭头样式的CSS3气泡提示框
2016/03/16 HTML / CSS
Kate Spade美国官网:纽约新兴时尚品牌,以包包闻名于世
2017/11/09 全球购物
英语系毕业生自荐信
2013/10/31 职场文书
2014年社区庆元旦活动方案
2014/03/08 职场文书
本科毕业自我鉴定
2014/03/20 职场文书
主题班会演讲稿
2014/05/22 职场文书
数据保密承诺书
2014/06/03 职场文书
保护地球的标语
2014/06/17 职场文书
解除劳动合同证明书
2014/09/26 职场文书
护理实习生带教计划
2015/01/16 职场文书
同事离别感言
2015/08/04 职场文书
详解JavaScript中Arguments对象用途
2021/08/30 Javascript
sass 常用备忘案例详解
2021/09/15 HTML / CSS