使用Async/Await中断while循环



上下文:我有一个while循环,我想运行10次,其中我有每3秒运行一次的async/await代码。如果while循环运行了10次,而async/await检查没有返回预期值,那么while循环就相当于超时。

问题:代码的循环中断部分首先运行,i(循环变量(的值达到最大值。正如我所想的那样,在循环时,我无法访问i的值,只有当i处于其最大值时。

问题:当条件满足或我筋疲力尽时,我如何尽早退出这个循环?

var i = 0;
//Run 10 Times
while (i < 10) {
//Run every 3 seconds
((i) => {
setTimeout( async () => {
isAuthenticated = await eel.is_authenticated()();
sessionStorage.sessionStatus = JSON.stringify(isAuthenticated);
console.log('------NEW STATUS-------');
console.log(JSON.parse(sessionStorage.sessionStatus).authenticated);
console.log('Inside:' + i);
}, 3000 * i)
})(i++);
//Break out of loop early if condition is met or I is exhausted, but it only runs 1 time and i is always max
if (i === 9 || JSON.parse(sessionStorage.sessionStatus).authenticated) {
console.log('Outside:' + i);
checkStatus('retried');
break;
}
}

注意:如果有人想知道eel.is_authenticated()();不是打字错误,那么它是一个用于创建桌面应用程序的python库,double((((是正常的

此外,如果这种方法的作用过于复杂,欢迎使用任何其他方法:(

感谢

这里的问题是,您正在立即运行所有循环迭代(10次(,在过程中设置10个超时,彼此间隔3秒:

  1. 循环运行10次,产生10次超时
  2. 您到达i === 9案例
  3. 3秒后,第一次超时
  4. 3秒后,第二次超时

您想要的是循环在迭代之间实际等待3秒。为此,您可以用不同的方式使用setTimeout——您可以创建一个在超时时解析的promise和一个promise的await

// As helper function for readability
const delay = ms => new Promise(resolve => setTimeout(resolve, ms));
// Your loop
let i;
for (i = 0; i < 10; i++) {
// Wait 3s
await delay(3000);
// Check authentication
const isAuthenticated = await eel.is_authenticated()();
sessionStorage.sessionStatus = JSON.stringify(isAuthenticated);
console.log('------NEW STATUS-------');
console.log(JSON.parse(sessionStorage.sessionStatus).authenticated);
console.log('Inside:' + i);
// Break loop if authenticated
if (isAuthenticated.authenticated) break;
}
// We were authenticated, or looped 10 times
// Note: Because I moved this outside, i will now actually be 10 if the loop
// ended by itself, not 9.
console.log('Outside:' + i);
checkStatus('retried');

然而,这里的一个后果是,如果对is_authenticated的调用需要相当长的时间,则检查间隔将超过3s,因为我们现在正在等待此调用的3s。如果这是不希望的,我们可以根据自上次呼叫以来经过的时间来减少延迟时间:

// As helper function for readability
const delay = ms => new Promise(resolve => setTimeout(resolve, ms));
// We will save here when the last delay completed, so that the checks are always
// 3s apart (unless the check takes longer than 3s)
// Initially we save the current time so that the first wait is always 3s, as before
let lastIteration = Date.now();
// Your loop
let i;
for (i = 0; i < 10; i++) {
// Wait until 3s after last iteration (limited to 0ms, negative waits won't work)
await delay(Math.max(lastIteration + 3000 - Date.now(), 0));
// Update "last iteration" time so the next delay will wait until 3s from now again
lastIteration = Date.now();
// Check authentication
const isAuthenticated = await eel.is_authenticated()();
sessionStorage.sessionStatus = JSON.stringify(isAuthenticated);
console.log('------NEW STATUS-------');
console.log(JSON.parse(sessionStorage.sessionStatus).authenticated);
console.log('Inside:' + i);
// Break loop if authenticated
if (isAuthenticated.authenticated) break;
}
// We were authenticated, or looped 10 times
// Note: Because I moved this outside, i will now actually be 10 if the loop
// ended by itself, not 9.
console.log('Outside:' + i);
checkStatus('retried');

所有这些都假定此代码所在的函数是async。如果不是,您需要将其设为async,但在调用它时需要记住添加.catch(e => handleTheErrorSomehow(e)),以避免未经处理的承诺拒绝!

最新更新