J.Doe
J.Doe

Reputation: 1137

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?

Upvotes: 1

Views: 129

Answers (2)

Rex Low
Rex Low

Reputation: 2177

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.

Upvotes: 1

Quentin
Quentin

Reputation: 944443

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

Upvotes: 1

Related Questions