js如何优雅的轮训接口

108 阅读1分钟

我们在开发过程中,一般都是用setInterval轮训接口。别问我为啥不用websocket。就会有几个问题

  1. setInterval没办法在创建的时候立即调用
  2. 请求超过了轮训时间,会很尴尬。我3秒轮训一次,结果接口3秒后才返回,那我的轮训岂不是很呆
  3. 后端异常了,但是我的轮训不会停,导致页面一直在报错

上代码

class MyInterval {
    constructor(/* callback, interval, times */) {
        this.timer = null;
        // this.callback = callback;
        // this.interval = interval;
        // this.times = times;

        this.currentTimeF = 0;
        this.currentTimeS = 0;
        this.index = 0;
    }

    init(callback, interval, times) {
        this.callback = callback;
        this.interval = interval;
        this.times = times;
        this.currentTimeF = 0;
        this.currentTimeS = 0;
        this.index = 0;

        this.callback({
            success: this.success,
            fault: this.fault,
            clear: this.clear
        });
        this.clear();
        // this.action();
        this.success();
    }

    action() {
        let _i = Array.isArray(this.interval) && this.interval?.[this.index] > 0 ? this.interval[this.index] : this.interval;

        if (typeof _i === 'number') {
            this.clear();
            this.timer = setTimeout(() => {
                this.callback(this);
            }, _i);
        }
    }

    clear() {
        clearTimeout(this.timer);
    }

    fault() {
        this.currentTimeS = 0;
        if (Array.isArray(this.interval) && this.interval.length > 0) {
            this.currentTimeF++;
            if (this.currentTimeF >= this.times) {
                this.index++;
                if (this.index > this.interval.length - 1) {
                    this.index = this.interval.length - 1;
                }
                this.currentTimeF = 0;
            }
        }
        this.action();
    }

    success() {
        this.currentTimeF = 0;
        if (Array.isArray(this.interval) && this.interval.length > 0) {
            this.currentTimeS++;
            if (this.currentTimeS >= this.times) {
                this.index--;
                if (this.index < 0) {
                    this.index = 0;
                }
                this.currentTimeS = 0;
            }
        }
        this.action();
    }
}

用法


            let myInteval = new MyInterval();
            myInteval.init(
                instant => {
                    // console.log('callback');
                    // if (window.a === 0) {
                    //     instant.fault();
                    // } else {
                    //     instant.seccuss();
                    // }
                    fetch('www.baidu.com').then(res => {
                        instant.seccuss();
                    }).catch(err => {
                        instant.fault()
                    })
                },
                [1000, 2000, 3000, 4000],
                3
            );

大概干了啥事

对应开头的三个问题我的解决方案是,

  1. setInterval不能立即调用,那我就手动调用呗
  2. 接口时间太长,就用setTImeout模拟setInterval,接口成功也就是你调用success的时候再开启下一次轮训
  3. 设置梯度,内部对success和fault计数,不断更改轮训的时间,接口异常次数多了,就降低梯度

几十行代码,随便看看。对了,有bug记得提醒我,

========================================================

话说有没有大佬有现成的库推荐的,让我cv一下