简体   繁体   中英

How to pause a Javascript asynchronous function without setTimeout?

I have a function that checks the existence of token in the database. The problem is it takes some amount of time to return that bool value and I kinda need to pause the function so that the function realizes that the token has existed and run the query again.

 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); } 

My setup is basically a do-while loop, when the function first gets call tokenExisted = null , then a random 4 digit token will be generated and a query will be dispatched to firebase and verify it token has existed.

If token has existed, then tokenExisted = true . I expect it the assignment to be executed but the single threaded nature of Javascript will reach the end of the loop before the query return anything.

I figured to use setTimeout and periodically add some small amount of time whenever tokenExisted = null to kinda safe guard so that the function will always catch when query function returns anything.

Has anyone had a better approach to achieve the same thing?

Call the function recursively.

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);
        }
    }
}

You might want to call the function itself recursively, as such.

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 => {} ))
}

The logic is that token will be refreshed during each new iteration, should the process fails and a new query is needed (if this is what you need).

Note : avoid using do-while in async logic. Plan carefully ahead as you might encounter lots of logic error and it is hard to trace.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM