0

I'm trying to place a delay between api calls within a for loop. I've tried using the setTimeout() without any luck.

Here is the code:

for(let pc = 0; pc < this.cModel.stuff.length; pc++)
{   
   for(let mc = 0; mc < this.cModel.stuff[pc].otherStuff.length; mc){
       let mp = this.mcModel.stuff[pc].otherStuff[mc];

       //method that calls api ***need delay***
       this.callCancel(mp.key, cp.key);
   }
}
private (mpkey: string, cpkey: string){
       //code that builds up object *obj
       //for api call here

       this.executeApiCallHere(obj);
    }

Here is what I've tried:

  • I've tried putting the setTimeout() inside the forloop as such:

    setTimeout(this.callCancel(mp.key, cp.key), 1000);
    
  • I've tried putting the setTimeout() inside the method that calls the api as such:

    setTimeout(() => { this.executeApiCallHere(obj);}, 1000);
    
  • I've tried placing the setTimeout() around the forloop as such:

    setTimeout(function () { ......code ....}, 1000);
    

All of the above result with no delay between calls. How should I handle this in Typescript so that foreach item in the forloop there is a delay between calls?

1
  • 1
    you should use rxjs for this. I can post an example if you're interested in trying it. Commented Aug 15, 2017 at 19:40

2 Answers 2

2

If you run a loop 10 times and call setTimeout in that loop with 1 second the result will be a 1 second delay and then a rapid continues fire of the callbacks that you had delayed. The result is an initial delay but not a delay between calls.

If you want to delay between calls you have to increase the timeout between each call of setTimeout. You can do this with a counter or using the value in the for loop (depending on the places you call it).

Example

var timeoutSeconds = 1;

for(let pc = 0; pc < this.cModel.stuff.length; pc++)
{   
   for(let mc = 0; mc < this.cModel.stuff[pc].otherStuff.length; mc){

      setTimeout(() => this.callCancel(mp.key, cp.key), 1000 * timeoutSeconds);
      timeoutSeconds++;

   }
}
Sign up to request clarification or add additional context in comments.

2 Comments

In this case pc and mc are already counters so you don't need timeoutSeconds :) Also, the keyword this loses its scope, you can prevent that with setTimeout(() => this.callCancel(mp.key, cp.key), 1000 * mc);
@Kokodoko - good catch on this losing scope! On the counters this is just an example to illustrate the point that calling it repeatedly with 1 second as the 2nd argument will not space anything. I did not use mc because the value will reset back to 0 each time the outer loop iterates and I did not want to assume that the next (set) of calls should or should not also be spaced from the first set. The OP can edit it as he sees fit.
2

async / await are your friends:

async function modelStuff() {
    for (let i = 0; i < 5; i++) {
        try {
            await apiCall(i);
        } catch (err) {
            // do we keep going?
            // do we drop the rest?
            // do we maybe need to relogin and retry last request?
        }
        await sleep(500);
    }
}

async function apiCall(ix) {
    console.log(`call: ${ix}`);
}

function sleep(ms) {
    return new Promise(resolve => setTimeout(resolve, ms));
}

// test it
modelStuff();

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.