如何重写setInterval方法

created() {

this.interval = setInterval(async () => {

const resp = await getNewStatistics();

this.rows = resp.rows;

}, 500);

}

destroyed() {

clearInterval(this.interval);

}

其中getNewStatistics()是访问后端的异步操作

  1. 发现异步操作getNewStatistics()返回速度有点慢, 导致操作出现堆积, 现要求实现一个函数 setIntervalWaitable(callback, ms) 代替上述代码中的setInterval,要求异步函数callback完成后,等待ms的时间,再重新执行callback
  2. 将1中的setIntervalWaitable函数的行为修改为如下方式该怎么实现:

  • 等待传入的ms时间,如果此时callback已经完成,重新执行callback
  • 否则,等待callback完成,之后立刻重新执行callback

  1. (选答)为上面实现的setIntervalWaitable函数提供一个可停止实现,用于代码中的destroyed()方法当中

回答

看着是个 setInterval,实际是个 setTimeout

function setIntervalWaitable(callback, ms = 0) {

// 参数校验省略

const fn = (async () => {

try {

await callback();

} catch (err) {

console.error(err);

}

setTimeout(fn, ms); // 递归调用

});

setTimeout(fn, ms); // 立即触发一次

}

测试结果(模拟 AJAX 请求阻塞 5 秒,上一次请求结束后等 5 秒再开始下一次,即 5+5=10):

image.png

https://codesandbox.io/s/bar-...

function getNewStatistics() {

return new Promise((resolve, reject) => {

setTimeout(() => {

resolve(Date.now());

}, 2000);

});

}

function setIntervalWaitable(callback, delay) {

let _abortRejector;

const internal = () => {

const ret = Promise.race([

Promise.all([

callback(),

new Promise(resolve => setTimeout(() => resolve(), delay))

]),

new Promise((_, reject) => (_abortRejector = reject))

]);

ret.then(

() => internal(),

_ => {

if (_.message !== "abort") throw _;

}

);

};

internal();

return () => {

_abortRejector(new Error("abort"));

};

}

class Foo {

constructor() {

this.abort = null;

this.created();

document.documentElement.onclick = () => this.abort();

}

created() {

this.abort = setIntervalWaitable(async () => {

console.log("begin");

const resp = await getNewStatistics();

console.log("end", resp);

}, 500);

}

destroyed() {

this.abort();

}

}

new Foo();

以上是 如何重写setInterval方法 的全部内容, 来源链接: utcz.com/a/25478.html

回到顶部