如何重写setInterval方法
created() {this.interval = setInterval(async () => {
const resp = await getNewStatistics();
this.rows = resp.rows;
}, 500);
}
destroyed() {
clearInterval(this.interval);
}
其中getNewStatistics()是访问后端的异步操作
- 发现异步操作getNewStatistics()返回速度有点慢, 导致操作出现堆积, 现要求实现一个函数
setIntervalWaitable(callback, ms)
代替上述代码中的setInterval
,要求异步函数callback完成后,等待ms的时间,再重新执行callback - 将1中的
setIntervalWaitable
函数的行为修改为如下方式该怎么实现:
- 等待传入的ms时间,如果此时callback已经完成,重新执行callback
- 否则,等待callback完成,之后立刻重新执行callback
- (选答)为上面实现的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):
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