文档章节

轻量级 JS 任务调度工具 bobolink

孟飞阳
 孟飞阳
发布于 2018/07/27 17:54
字数 1598
阅读 20
收藏 0

项目介绍

轻量级 JS 任务调度工具,允许并行数控制,超时,重试,错误抓取,运行状态统计等,同时支持多种调度模式,包括立即调度、按频率调度等。

为什么说任务执行队列对 JS 来说比其它热门语言更为重要?由于 JS 是事件驱动型的动态脚本语言,我们最常见到的就是在代码里各种各样的异步回调,NodeJs 标榜的轻量高效也是基于 Javascript 非阻塞 I/O 模型而谈的,可以说,基于回调的编程思维是 JS 的一大特色,但有时它会出问题,例如在 for 循环中执行异步任务,由于每个任务都是瞬间返回的,也就是说,循环会很快遍历完,但任务却是堆积的,轻则服务繁忙,重则直接把服务压垮,如何轻巧地控制任务并行量很多时候是一个痛点。

安装

npm i bobolink

使用说明

  1. 创建一个默认配置的Bobolink

    按照需要创建一个Bobolink实例(Bobolink实例之间互不影响, 所以可以多种场景使用多个Bobolink,甚至可以通过多个Bobolink合从而应对一些复杂场景)

    const Bobolink = require('bobolink');
    // 每个Bobolink实例都有一个大的队列用于存放任务,所以可以很放心地将任务扔给它,适当的时机下Bobolink会很可靠地调度这些任务。
    let q = new Bobolink();
  2. put单个任务

    由于Promise的执行代码在创建的时刻就已经被执行(then和catch内的代码则通过回调执行),所以简单把Promise扔进Bobolink是不可行的

    // 下面的打印序是 1 2 3
    new Promise(resolve => {
        console.log(1);
        resolve(3)
    }).then(res => {
        console.log(res);
    })
    console.log(2)

    通过将Promise扔进一个function可以达到延期执行的效果

    function p() {
        // 返回promise任务
        return new Promise(resolve => {
            console.log(1);
            resolve(3)
        }).then(res => {
            console.log(res);
        })
    }
    console.log(2);

    此时p必须等待调用才会执行内部的Promise代码,且p返回的是该Promise,值便可以继续传递。 每个放置到Bobolink的Promise任务都应该以这种方式封装

    function p() {
        return new Promise(resolve => {
            console.log(1);
            resolve(2)
        }).then(res => {
            console.log(res);
            return 3;
        })
    }
    // 由于队列很空闲, 可以立即调度本任务,
    // 所以很快就成功打印出了1, 之后的then则需要等待合适的时机回调,
    // 如果Promise及其上面的所有then都执行完了, 最终会传递到put.then
    q.put(p).then(task => {
        // 打印最终值3
        console.log(task.res)
    });

    当然,如果在put的时候,队列执行中的任务数已经到达最大并行量,则需要等待有任务执行完成时腾出空间,并且排在当前任务之前的任务已经都被调度完了才会得到执行。

  3. put一组任务

    Bobolink允许同时put多个任务,且put.then会在该组任务都被执行完毕时才被调用

    function getP(flag) {
        return function p() {
            return new Promise(resolve => {
                resolve(flag)
            });
        }
    }
    q.put([getP(1), getP(2), getP(3)]).then(tasks => {
        // 打印每个任务的返回值, 按放入顺序一一对应
        for (let i = 0; i < tasks.length; i++) {
            console.log(tasks[i].res);
        }
    })
  4. 配置

    目前支持的参数如下:

    let q = new Bobolink({
       // 最大并行数,最小为1
       concurrency: 5,
       // 任务超时时间ms,0不超时
       timeout: 15000,
       // 任务失败重试次数,0不重试
       retry: 0,
       // 是否优先处理失败重试的任务,为true则失败的任务会被放置到队列头
       retryPrior: false,
       // 是否优先处理新任务,为true则新任务会被放置到队列头
       newPrior: false,
       // 最大可排队的任务数, -1为无限制, 超过最大限制时添加任务将返回错误'bobolink_exceeded_maximum_task_number'
       max: -1,
       // 指定任务的调度模式,仅在初始化时设置有效
       scheduling: {
         // 默认为'immediately',任务将在队列空闲时立即得到调度。
         // 你也可以将它设置为'frequency', 并且指定countPerSecond, Bobolink将严格地按照设定的频率去调度任务。
         enable: 'frequency',
         frequency: {
           // 每秒需要调度的任务数,仅在任务队列有空闲时才会真正调度。
           countPerSecond: 10000
         }
       },
       // 任务失败的handler函数,如果设置了重试,同个任务失败多次会执行catch多次
       catch: (err) => {
    
       }
    });

    参数可以在运行期更改, 对后续生效

    q.setOptions({
       concurrency: 5,
       timeout: 15000,
       retry: 0,
       retryPrior: false,
       newPrior: false,
       catch: null
    });
  5. 任务运行状态

    使用Bobolink执行的Promise任务所有错误会被catch并包装,所以只存在put.then而不存在put.catch(除非put.then自身出错)。任务执行之后获取到的响应有一些有用的值可以用于服务统计

    taskRes = {
        // 执行是否遇到错误, 判断任务是否执行成功的判断依据是err === undefined, err为任何其它值都代表了运行失败。
        // 任务出错时, 如果不重试, 那么catch到的错误会直接放入err, 超时时err为'bobolink_timeout'
        // 如果重试, 且在最大重试次数之后依然错误的话, 会将最后一次的错误放入err
        // 如果重试, 且在重试期间成功的话, 被认为是成功的, 所以err为空
        err: undefined,
        // 执行Promise返回的结果
        res: Object,
        // 从任务放入队列到该任务最后一次被调度, 所经过的时间(ms)
        waittingTime: 20,
        // 该任务最后一次运行的时间(ms)
        runTime: 1,
        // 该任务出错重试的次数
        retry: 2
    }
  6. 插队

    除了队列控制参数newPrior和retryPrior之外,也允许在put的时候指定当前任务是否优先处理

    Bobolink.ptototype.put(tasks, prior)

    默认情况下,任务是放入队尾的,但如果指定了prior为true,则会被放置到队头,put任务组时会维持组任务原本的顺序,并整个放入队头。

  7. 更多

    • q.options:获取当前队列的配置。

    • q.queueTaskSize:获取队列排队中的任务数。

    • q.runningTaskCount:获取队列执行中的任务数。

本文转载自:https://www.oschina.net/p/bobolink

共有 人打赏支持
孟飞阳
粉丝 212
博文 997
码字总数 550227
作品 5
朝阳
个人站长
私信 提问
轻量级 JS 任务调度工具 - bobolink

. . . . __ | _ | | | || | | | / | / | | | |/ | |/ / | _ ( <> ) _ ( <> ) || | | < | //| /_/|/|| /| / / / / 项目介绍 轻量级 JS 任务调度工具,允许并行数控制,超时,重试,错误抓取,......

blurooo
2018/07/19
0
0
使用scrapy的定制爬虫-第三章-爬虫的javascript支持

-.-编辑中.我语文是数学老师教的... 后续补充参考代码,链接. 很多网站都使用javascript...网页内容由js动态生成,一些js事件触发的页面内容变化,链接打开.甚至有些网站在没有js的情况下根本不...

斑ban
2013/04/04
0
4
js Event Loop 运行机制

Event Loop,事件环,线程进程。这些概念对初识前端的同学来说可能会一头雾水。而且运行js代码的运行环境除了浏览器还有node。因此不同环境处理Event Loop又变得不同,十分容易混淆。如果你有...

satomiyoyi07
2018/08/06
0
0
异步 JavaScript - 事件循环

简评:如果你对 JavaScript 异步的原理感兴趣,这里有一篇不错的介绍。 在介绍 JavaScript 异步执行之前先来了解一下, JavaScript 同步代码是如何执行的。 这里有两个概念需要了解: 执行上...

极光推送
2018/12/05
0
0
2014年12月最棒的 15 个 JavaScript 库

JavaScript提供了丰富的函数库,不管是事件,效果,还是AJAX。如果偶尔出现JavaScript库没法做某样工作,那一定会有一个插件可以做到! 这种库提供的灵活性用起来杠杠的。不过,它们其中的一...

oschina
2014/12/09
8.5K
14

没有更多内容

加载失败,请刷新页面

加载更多

kubernetes 二进制包安装

环境 角色 主机名 内网 IP 集群 IP 操作系统 服务 执行目录 部署机 k8s-master master120 10.0.4.120 - CentOS kube-apiserver kube-scheduler kube-controller-manager /opt/kubernetes/ et......

Colben
3分钟前
0
0
瑞达利欧的《原则》读后感作文2400字

瑞达利欧的《原则》读后感作文2400字: 拿到同事送的书读了几十页后,我意识到自己犯了一个错误:之前以为像《原则》这个书名,配上最成功的对冲基金经理、受用终身的教诲、傅盛引用并盛赞,...

原创小博客
21分钟前
1
0
java内存占用异常问题常见排查流程(含堆外内存异常)

先初步介绍一下内存组成: java进程占用内存 约等于 Java永久代 + Java堆(新生代和老年代) + 线程栈+ Java NIO,其它部分占用内存较小, 详细可以参考这篇文章 https://my.oschina.net/h...

小海bug
27分钟前
0
0
成为架构师需要学习哪些技能?阿里P9架构师为你解答

不想当将军的兵不是好兵,就程序猿不想当架构师就不是好的程序员! Java架构师主要需要做哪些工作呢? 1、负责设计和搭建软件系统架构(平台、数据库、接口和应用架构等),解决开发中各种系...

别打我会飞
31分钟前
0
0
使用xtrabackup备份数据库

使用xtrabackup备份数据库 提供一个参考文档:http://xtra.aminglinux.com mysqldump对于导出几个G的数据库或几个表,还是不错的,速度并不慢。一旦数据量达到几十上百G,无论是对原库的压力...

wzb88
46分钟前
1
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部