Neeraj Sewani
Neeraj Sewani

Reputation: 4287

Ambiguous behavior of setTimeout when used with promises

I wanted to run an async method inside a promise for every x seconds until a specific condition is met and then call resolve() to resolve the promise. I tried it using two approaches(shown below). The second approach is devised using IIFE and is giving the correct results but in the first approach, the setTimeout method is running just once but according to the def. of setTimeout it should execute a callback indefinitely after a specified amount of time until clearTimeout() is called. Can anyone explain to me why am I not getting the desired output in the first approach?

Approach 1

function func2() {
    return new Promise((resolve, reject) => {
        setTimeout(() => {

            client.get('statuses/user_timeline', params1).then((response) => {
                //    some code
                //    some code

                if (condition is met) {
                    return resolve()
                } else {
                    //    some code
                }
            })
        }, 1000)
    })
}

Approach 2

function func2 () {
    return new Promise((resolve, reject) => {
        (function func1() {
            client.get('statuses/user_timeline', params1).then((response) => {
                //    some code
                if (condition is met) {
                    return resolve()
                } else {
                    //    some code
                    setTimeout(func1, 1000)
                }
            })
        })()
    }
}

Upvotes: 2

Views: 68

Answers (2)

Ivan Drinchev
Ivan Drinchev

Reputation: 19581

You can achieve it with recursive functions

function waitForTimeline() {
   return client
       .get('statuses/user_timeline', params1)
       .then((response) => {
           if (condition is met) { return response }
           // In case the condition was not met, just call the same function
           // after a second
           return new Promise( ( resolve, reject ) => {
               setTimeout( () => {
                  waitForTimeline()
                      .then( resolve )
                      .catch( reject )
               }, 1000 );
           } );     
       }
};

Upvotes: 2

mika
mika

Reputation: 343

setTimeout() executes the function only once, i think you're looking for setInterval(). It works the same way, but in executes the function indefinitely unit clearInterval() is called on it.

This would be your function:

function func2() {
return new Promise((resolve, reject) => {
  let interval = setInterval(() => {

  client.get('statuses/user_timeline', params1).then((response) => {
    //    some code
    //    some code

    if (condition is met) {
      clearInterval(interval)
      return resolve()
  } else {
    //    some code
  }
})
}, 1000)
})
}

Upvotes: 2

Related Questions