classes_polling.js

/**
 * @class Polling
 * @extends EventTarget
 * @description 轮询类
 * @param {Object} options 轮询选项
 * @param {Function} options.request 请求方法
 * @param {Function} [options.needToPolling = ()=>true] 是否需要继续轮询的检查方法,默认
 * @example
 * const pollingInstance = new Polling({
 *  // 轮询的请求
 *  request:()=>fetch('/data'),
 *  // 可选:在此判断是否继续轮询,不传默认持续轮询
 *  needToPolling: (res) => {
 *    const undoneCount = 1;
 *    return undoneCount > 0;
 *  },
 * });
 * // 每次轮询请求回来的数据更新事件
 * pollingInstance.addEventListener('update',(res)=>{
 *  console.log(res)
 * })
 * // 轮询结束
 * pollingInstance.addEventListener('end',()=>{
 *  console.log('end')
 * })
 * // 开始轮询
 * pollingInstance.start()
 * // 主动结束
 * pollingInstance.stop()
 */
export class Polling extends EventTarget {
    /**
     * @ignore
     * @param {Object} options 轮询选项
     * @param {Function} options.request 请求方法
     * @param {Function} [options.needToPolling = ()=>true] 是否需要继续轮询的检查方法,默认
     */
    constructor({ request, needToPolling = () => true }) {
        super();
        // 请求
        this.request = request;
        // 检查是否需要继续轮询
        this.needToPolling = needToPolling;
        this.pollingListTimer = null;
        this.delay = 3000;
        this.pollingId = 0;
        this.onRequestPollingList = false;
        this.requestErrorCount = 0;
    }
    /**
     * @description 开始轮询
     */
    async start() {
        const needPolling = await this.needToPolling();
        if (needPolling) {
            let delay = this.delay * (this.requestErrorCount + 1);
            delay = delay > 30000 ? 30000 : delay;
            this.pollingListTimer = setTimeout(() => {
                this.polling();
            }, delay);
        }
    }
    /**
     * @description 停止
     */
    async stop() {
        // 更新轮询id,所有请求废弃
        this.pollingId = this.pollingId + 1;
        clearTimeout(this.pollingListTimer);
        this.onRequestPollingList = false;
        this.requestErrorCount = 0;
    }
    /**
     * @description 开始轮询
     * @ignore
     */
    async polling() {
        const pollingId = this.pollingId;
        if (this.onRequestPollingList) {
            return false;
        }
        this.onRequestPollingList = true;
        try {
            const res = await this.request();
            // 重置请求错误状态为0
            this.requestErrorCount = 0;
            // 如果已经变更了轮询id,则废弃
            if (pollingId !== this.pollingId) {
                this.onRequestPollingList = false;
                return false;
            }
            // 更新数据
            this.dispatchEvent(new CustomEvent("update", { detail: res }));
            // 传入新数据由调用者判断是否需要继续轮询
            const needPolling = await this.needToPolling(res);
            // 不再需要轮询表示轮询已结束
            if (!needPolling) {
                this.dispatchEvent(new Event("end"));
                this.onRequestPollingList = false;
                return false;
            }
        } catch (error) {
            this.requestErrorCount++;
            console.log(error);
        }
        this.start();
        this.onRequestPollingList = false;
    }
}