2017-07-25 95 views
0

我有一個函數來檢查數據庫中令牌的存在。問題是需要一定的時間才能返回該值,我需要暫停該函數,以便該函數可以實現該令牌已存在並再次運行該查詢。如何在沒有setTimeout的情況下暫停Javascript異步函數?

const registerToken = dispatch => { 
 
    var tokenExisted = null 
 
    do { 
 
    let token = generateRandomToken(); 
 
    firebase.database().ref(`/Token`).orderByChild("token").equalTo(token).once("value", snapshot => { // check whether token exists 
 
     if (!snapshot.val()) { // if token not exist 
 
     token = false; 
 
     // register token to firebase 
 
     } else { 
 
     token = true; // continue the loop to generate a new token and query again 
 
     } 
 
    }) 
 
    } while (tokenExisted === true); 
 
}

我的設置基本上是一個do-while循環,當函數首先得到調用 tokenExisted = null,然後隨機4位數的令牌生成的,以及查詢將被分派到火力地堡和驗證它的標記已經存在。

如果令牌已經存在,那麼tokenExisted = true。我期望它的賦值被執行,但是在查詢返回任何東西之前,Javascript的單線程特性將會到達循環的結尾。

我打算使用setTimeout,並且每當tokenExisted = null有時會添加一些少量的時間以提供安全防護,以便在查詢函數返回任何內容時該函數總能捕獲。

有沒有人有更好的方法來實現同樣的事情?

+5

異步代碼的完全錯誤的方法。在異步調用的回調中,您要麼滿意,要麼觸發另一個異步調用。你不能在這裏使用同步的'do..while'。 – deceze

+0

更不用說,你不能暫停Javascript反正 – SDhaliwal

回答

1

您可能想要遞歸地調用函數本身。

const registerToken = dispatch => { 
    let token = generateRandomToken(); 
    const tokenObjectRef = firebase.database().ref(`/Token`); 

    tokenObjectRef.orderByChild("token").equalTo(token).once("value") 
    .then(snapshot => { 
     if (!snapshot.val()) { 
     // success! 
     } else { 
     registerToken(dispatch) // call itself again 
     } 
    }) 
    .catch(error => {})) 
} 

的邏輯是,令牌將每個新的迭代過程中被刷新,如果該方法失敗,需要一個新的查詢(如果這是你所需要的)。

備註:避免在邏輯中使用do-while。提前仔細計劃,因爲您可能會遇到很多邏輯錯誤,並且很難追蹤。

1

遞歸調用函數。

function get_token_then(callback_when_token_found) { 
    firebase.database().etc.etc(function (data) { 
     if (data == what_you_want) { 
      callback_when_token_found(data); 
     } else { 
      // You might want to wrap this in setTimeout in order to throttle your database calls 
      get_token_then(callback_when_token_found); 
     } 
    } 
} 
相關問題