javascript - setInterval 基于 ajax 结果或承诺状态
问题描述
我需要发送一个间隔为 5s 的 ajax 请求
const asyncF = async () => { await /* some ajax stuff */ }
asyncF(); // fire off an ajax request first
setInterval(() => { // start an interval
asyncF();
}, 5 * 1000);
通常asyncF
应该在 5 秒内成功,所以连续启动之间的 5 秒通常是好的和简单的,但我想确保下一个 asyncF 触发时,前一个已经成功。如果前一个没有成功,那么只要前一个成功就开始一个新的间隔
- 如果
asyncF
不到5s就成功了,一切都好! - 如果
asyncF
需要超过 5 秒才能成功,我需要清除间隔并在asyncF
成功时开始新的间隔 - 如果
asyncF
在 5 秒内失败,我还需要立即再次调用它并设置新的间隔
我想出了这个解决问题的天真的想法
let flag = true; // global variable flag
const asyncF = async () => {
await /* some ajax stuff */
flag = true;
}
try {
asyncF();
setTimer();
} catch {
asyncF();
setTimer();
}
function setTimer() {
let timer = setInterval(() => {
if (flag) {
asyncF();
} else {
clearInterval(timer);
timer = setTimer();
}
}, 5 * 1000);
return timer;
}
但是使用这种方法,如果asyncF
需要超过 5s 才能成功,则计时器在成功之前开始计数asyncF
有没有成熟优雅的解决方案来解决问题?
解决方案
不使用 a 更容易做到这一点,setInterval
并且必须确定何时取消/重新启动它,而是使用setTimeout
.
这个想法是您将计时器设置为 5 秒,如果前一个功能已完成,您将调用该功能。如果在函数执行时已达到超时,则立即执行它,如果发生错误也是如此。
async function limitedFunction(){
let isRunning = true;
let timeoutReached = false;
setTimeout( () => {
timeoutReached = true;
if(!isRunning)
limitedFunction();
},5000);
try{
await asyncF();
isRunning = false;
if(timeoutReached)
limitedFunction();
}
catch {
limitedFunction();
}
}
在下面的示例中,我模拟了您的asyncF
函数,它随机成功或失败(成功几率为 80%),并且随机延迟有时超过 5 秒。但是,这与基于 ajax 的异步函数没有什么不同。它的工作方式完全相同!
你应该看到
- 当函数在 <5s 内成功时,它会等待 5s,因为原始开始再次触发
- 当函数在 >5s 内成功时,它会立即重新启动
- 当功能失败时,它会立即重新启动。
希望这符合您的要求
async function asyncF(){
const delay = (ms) => new Promise(resolve => setTimeout(resolve,ms))
const rndFunc = Math.random();
const rndTime = Math.floor((Math.random() * 7) + 1);
if(rndFunc < 0.8){
console.log(`asyncF will succeed in ${rndTime}s`)
await delay(rndTime*1000)
}
else{
console.log(`asyncF will fail in ${rndTime}s`);
await delay(rndTime*1000)
throw "I failed"
}
}
async function limitedFunction(){
let isRunning = true;
let timeoutReached = false;
setTimeout( () => {
timeoutReached = true;
if(!isRunning)
limitedFunction();
},5000);
try{
await asyncF();
isRunning = false;
if(timeoutReached)
limitedFunction();
}
catch {
limitedFunction();
}
}
limitedFunction()
推荐阅读
- javascript - 每次调用函数时 JavaScript 都会改变值
- javascript - 将表单输入与 JSON 文件匹配 [已解决 ✔ ]
- vim - 如何找到 vim 默认键绑定的功能?
- javascript - 在 foreach 循环中添加 onclick 事件侦听器不起作用
- python - 无法在 Selenium (Python 3.7) 中为 chrome 设置代理
- google-chrome - 在 chrome 隐身模式下访问 cookie
- android - 这两个上下文代码有什么不同?
- python-3.x - 如何从查询中获取列名?
- tensorflow - 为什么小型网络(<2k 参数)超过 Keras 优化器的限制?
- python - 检查行是否包含在 CSR 矩阵中