欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

详解Node.js串行化流程控制

程序员文章站 2023-01-07 21:12:57
串行任务:需要一个接着一个坐的任务叫做串行任务。 可以使用回调的方式让几个异步任务按顺序执行,但如果任务过多,必须组织一下,否则过多的回调嵌套会把代码搞得很乱。 为了用...

串行任务:需要一个接着一个坐的任务叫做串行任务。

可以使用回调的方式让几个异步任务按顺序执行,但如果任务过多,必须组织一下,否则过多的回调嵌套会把代码搞得很乱。

为了用串行化流程控制让几个异步任务按顺序执行,需要先把这些任务按预期的执行顺序放到一个数组中,这个数组将起到队列的作用:完成一个任务后按顺序从数组中取出下一个。

数组中的每个任务都是一个函数。任务完成后应该调用一个处理器函数,告诉它错误状态和结果。

为了演示如何实现串行化流程控制,我们准备做个小程序,让它从一个随机选择的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));

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。