簡體   English   中英

使用 Async/Await 跳出 while 循環

[英]Break out of while loop with Async/Await

上下文:我有一個 while 循環,我想運行 10 次,並且在其中我有每 3 秒運行一次的異步/等待代碼。 如果 while 循環運行了 10 次並且 async/await 檢查沒有返回預期值,那么它就像超時一樣工作,然后退出 while 循環進程超時。

問題:代碼的跳出循環部分首先運行,並且 i(loop variable) 的值已達到最大值。 當我想出我設置它的方式時,我無法訪問 i while 循環的值,只有當 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 秒后,第二次超時運行
  5. ...

您想要的是循環在迭代之間實際等待 3 秒。 為此,您將以不同的方式使用setTimeout - 您將創建一個 promise 來解決超時問題並await promise:

// 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的調用花費大量時間,則檢查間隔將超過3 秒,因為我們現在正在等待 3 秒此調用。 如果這是不希望的,我們可以根據自上次調用以來經過的時間來減少延遲時間:

// 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');

所有這些都假設此代碼所在的 function 是async 如果不是,您需要將其設為async ,但是您需要記住在調用它時添加.catch(e => handleTheErrorSomehow(e))以避免未處理的 promise 拒絕!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM