如何在没有setTimeout的情况下暂停Javascript异步函数?

时间:2017-07-25 07:59:33

标签: javascript reactjs firebase firebase-realtime-database logic

我有一个检查数据库中令牌是否存在的函数。问题是返回bool值需要一些时间,我需要暂停函数,以便函数意识到令牌已经存在并再次运行查询。

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位数令牌,并将查询调度到firebase并验证它是否存在令牌。

如果存在令牌,则tokenExisted = true。我希望它可以执行赋值,但是在查询返回任何内容之前,Javascript的单线程特性将到达循环的末尾。

我想使用setTimeout并定期添加一些少量的时间tokenExisted = null以保护安全,以便在查询函数返回任何内容时函数将始终捕获。

有没有人有更好的方法来实现同样的目标?

2 个答案:

答案 0 :(得分: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);
        }
    }
}

答案 1 :(得分: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逻辑中使用async。仔细地提前计划,因为您可能会遇到很多逻辑错误并且很难追踪。