Lars Mohammed
Lars Mohammed

Reputation: 117

How to await a specific value to exist in javascript?

So I've been trying to google my answer but had no luck finding it. I'm wondering how I can await a value to be defined by the use of promises, not a brute-force method like using:

while(true){ Check for condition and then break }

This was my initial brute-force approach but It obviously isn't a good solution:

const awaitToken = new Promise((resolve, reject) => {
    while(true){
        if(getState().auth.token){
            resolve(true)
            break;
        }
    }
})


** EDIT: The getState method isn't asynchronous otherwise it would be way easier and why I'm implementing this is because there is a small delay from when the user is signed in to when the token is available in redux state **
I'm working on a react-redux project where I want to implement this however, my code is irrelevant because I don't want a case-specific answer. I would appreciate any help!

Upvotes: 0

Views: 890

Answers (3)

Kai Lehmann
Kai Lehmann

Reputation: 508

Here is a non-blocking solution for using synced functions an easy way in promises. An additional timeout can save you a lot of waiting time.

let arrivedToken = new Promise((resolve, reject) => {
  /* how often you wanna check? */
  let interval = 20;
    /*how long do you want to wait? */
  let timeOut = 4000;
  let timer = setInterval(() => {
    timeOut -= interval;
    if (timeOut < 1) {
      clearInterval(timer);
      reject(new Error('catching token timed out'));
    }
    let token = getState().auth.token;
    if (token)
            resolve(token);
  }, interval);
};

so you can handle the success or even the failure:

arrivedToken
    .then(token => {
        /* whatever you want */
    })
    .catch(error => {
        /* handle the timeout */
  })
;

Upvotes: 1

Tobiah Rex
Tobiah Rex

Reputation: 2357

Push vs. Pull

I'm going to make some assumptions given the way you asked your question: The assumption is no-one has explained the Push v Pull dichotomy. It's extremely important to understand to solve these types of problems in the future without SO's community.

Promises and callbacks were designed by the ECMA body to enable developers to PULL for results of asynchronous tasks. You can think of PULL-ing as picking up the telephone and calling your friend asking him if your package has been delivered at his address that you used on your delivery form. Obviously you're not going to stay on the call until the package arrives so you continuously have to iterate this process until your friend says, "yes, you're package has arrived" (e.g. Promise.resolve(package) || cb('package has arrived')).

Then the ECMA body delivered us ES8. And with it, a PUSH methodology which solves exactly the problem that you're beating your head against quite admirably I might add. The async/await dichotomy enables a developer to no longer have to pick up the phone and call their friend. Instead, your friend picks up the phone and calls you and says "Hey man, come get your stuff off my porch, it's arrived." This is a PUSH. async/await & generators

More Verbosity on async/await theory if you desire here

Solutions

function * fetchToken() {
  const { auth } = getToken(); // getToken() is asynchronous and BLOCKs control flow until value is returned.
  yield auth.token;
}

const tokenGen = fetchToken();

const { value: token } = tokenGen().next();
console.log('token: ', token); // [jwt token]

async function fetchToken() {
  const { auth } = await getToken(); // await BLOCK's control flow until the function resolves. 
  return auth.token;
}

const token = fetchToken();
console.log('token: ', token); // [jwt token]

Upvotes: 0

3limin4t0r
3limin4t0r

Reputation: 21130

Redux allows you to subscribe to a store. The callback will be called whenever an action is dispatched.

Meaning you could do something like this:

const awaitToken = new Promise(resolve => {
  if (getState().auth.token) return resolve(true);

  const unsubscribe = subscribe(() => {
    if (!getState().auth.token) return;
    unsubscribe();
    resolve(true);
  });
});

Additional info about subscribe can be found here. You might also want to add a timeout, but that might depend on the use case.

Upvotes: 0

Related Questions