详解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 插件开发备注
Aug 27 Javascript
浅析Prototype的模板类 Template
Dec 07 Javascript
超简单JS二级、多级联动的简单实例
Feb 18 Javascript
javascript中call和apply的用法示例分析
Apr 02 Javascript
Javascript中的迭代、归并方法详解
Jun 14 Javascript
完美实现八种js焦点轮播图(上篇)
Jul 18 Javascript
实例解析jQuery工具函数
Dec 01 Javascript
jQuery仿IOS弹出框插件
Feb 18 Javascript
jquery实现焦点轮播效果
Feb 23 Javascript
js/jq仿window文件夹框选操作插件
Mar 08 Javascript
JavaScript实现修改伪类样式
Nov 27 Javascript
在Vant的基础上封装下拉日期控件的代码示例
Dec 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
盘点PHP和ASP.NET的10大对比!
2015/12/24 PHP
PHP根据session与cookie用户登录状态操作类的代码
2016/05/13 PHP
Linux php 中文乱码的快速解决方法
2016/05/13 PHP
Django中通过定时任务触发页面静态化的处理方式
2018/08/29 PHP
javascript 学习之旅 (2)
2009/02/05 Javascript
js正文内容高亮效果的实现方法
2013/06/30 Javascript
如何正确使用javascript 来进行我们的程序开发
2014/06/23 Javascript
我的Node.js学习之路(三)--node.js作用、回调、同步和异步代码 以及事件循环
2014/07/06 Javascript
js实现精美的图片跟随鼠标效果实例
2015/05/16 Javascript
js窗口震动小程序分享
2016/11/28 Javascript
Vue2.0用 watch 观察 prop 变化(不触发)
2017/09/08 Javascript
详谈DOM简介及节点、属性、查找节点的方法
2017/11/16 Javascript
js时间戳与日期格式之间转换详解
2017/12/11 Javascript
微信小程序后端实现授权登录
2020/02/24 Javascript
Python中input和raw_input的一点区别
2014/10/21 Python
python类装饰器用法实例
2015/06/04 Python
django之常用命令详解
2016/06/30 Python
用Python将mysql数据导出成json的方法
2018/08/21 Python
python3 unicode列表转换为中文的实例
2018/10/26 Python
Python创建或生成列表的操作方法
2019/06/19 Python
python twilio模块实现发送手机短信功能
2019/08/02 Python
python装饰器代码深入讲解
2021/03/01 Python
中国综合网上购物商城:苏宁易购
2016/08/09 全球购物
高街生活方式全球在线商店:AZBRO
2017/08/26 全球购物
DOM和JQuery对象有什么区别
2016/11/11 面试题
服装设计行业个人的自我评价
2013/12/20 职场文书
校园创业策划书
2014/01/14 职场文书
运动会广播稿150字
2014/02/19 职场文书
大学生创业项目方案
2014/03/08 职场文书
美术课外活动总结
2014/07/08 职场文书
忠诚教育心得体会
2014/09/03 职场文书
财务检查整改报告
2014/11/06 职场文书
工商局个人工作总结
2015/03/03 职场文书
简单的辞职信模板
2015/05/12 职场文书
小学信息技术教学反思
2016/02/16 职场文书
学校教代会开幕词
2016/03/04 职场文书