10. setTimeout, setInterval, and requestAnimationFrame
Tags: javascript, webdev, beginners, tutorial
Published: 2022-01-24 13:22:16

`setTimeout`, `setInterval`, and `requestAnimationFrame` are 3 most common APIs for scheduling call.
## SetTimeout & setInterval
### Definition

- `setTimeout` : allows us to run function once after given time.

- `setInterval` : allows us to run function repeatedly starting after given time, repeating continuously at the interval.
---

### setTimeout
#### syntax
> setTimeout(callback, delay, arg1, arg2,...)

Parameter from arg1, arg2,.. is optional.

Call to setTimeout returns "timer identifier" `timerId`.

We can use `clearTimeout` to cancel execution. The callback given as a parameter stays in memory untill we call `clearTimeout`.

---

### setInterval
Most parts of syntax is similar to `setTimeout`. Instead of `clearTimeout`, we use `clearInterval`. 
#### using setInterval & setTimeout for repeating function for given time period
``` jsx
let timerId = setInterval(()=>alert('tick'), 2000);

setTimeout(()=>{clearInterval(timerId); alert('stop');}, 5000);
```
In above snippet, we planned to print 'tick' for every 2sec, and it stops after 5sec.

---
### Nested setTimeout
For scheduling repeated function, there is a alternative for `setInterval`. It is using nested setTimeout. The advantage is that we can set delay between executions more precisely. It's more flexible.
``` jsx
let delay = 2000;
let timerId = setTimeout(function tick() {
  delay = 2000;
  console.log('tick');
  timerId = setTimeout(tick, 2000); // (*)
  const random = Math.random(0,1000);
  console.log(random)
  if(random%2 == 0) {
    delay = 1000;
  }
}, delay);
```
---
### setInterval vs Nested setTimeout
Note that both of methods **do not** guarantee exact delay of given time.
#### setInterval
`setInterval` calls function in given interval. It only guarantees that function will be passed to STACK in exeact interval. For example, if the given interval is 1sec, it means that function is called every 1sec.
![](https://images.velog.io/images/gtfo/post/172f70bf-2f7d-466b-9b1d-1a872ed670ea/image.png)
One big disadvantage of this mechanism is that It doesn't guarantees the interval of execution. If the previous function of`setInterval`'s execution takes lots of time, the callback of `setInterval` can be executed unexepectedly.
![](https://images.velog.io/images/gtfo/post/03e6df6a-6562-442d-abf9-1a18a47374c5/image.png)
#### Nested setTimeout
On the other hand, Nested setTimeout guarantees untill our method gets fully executed it will never be sent for another execution. 
![](https://images.velog.io/images/gtfo/post/3014df40-233f-4bb4-89ff-ef44e670a956/image.png)
![](https://images.velog.io/images/gtfo/post/4b606471-1fe5-4b0b-a54e-854e109baf11/image.png)

#### Other
Another alternative for handling repeating callback is using aync `setInterval`. 
``` jsx
const setIntervalAsync = (fn, ms) => {
  fn().then(() => {
    setTimeout(() => setIntervalAsync(fn, ms), ms);
  });
};

setIntervalAsync(() => fetch(/* blah */), 3000);
```

### Zero delay setTimeout
If we set interval of `setTimeout` to 0, it is not executed right away. The reason is because `setTimeout` is handled by Web API and task queue and then pushed to stack. So, it is scheduled '**right after**' the current script. If **current script is over**, which means that **stack is empty**, then it is executed.

---
## requestAnimationFrame
`requestAnimationFram` is used when we have to handle repeated animation changes in javascript.
### Why use requestAnimationFrame?
#### Problems with setTimeout & setInterval

- As mentioned above, the interval between animation is inconsistent.

- Layout thrashing happens. Layout thrashing is when browser is froced to perform unnecessary reflows of the page before the user's screen is able to display the changes.

#### Benefits of requestAnimationFrame

- It allows me to execute code on the enxt available screen repaint, which syncs with browser & hardware. It makes smoother animation.

- If the page is in inactive tabls, animation stops automatically, whcih saves system resources.

- Battery-friendly.

#### syntax
> requestAnimationFrame(callback)

Runs callback when screen is ready to accept the next screen repaint.
The callback function automatically passes `timestamp` which indicates the precise time `requestAnimationFrame` is called.
`requestAnimationFrame` returns non 0 integer that can be passed to `cancelAnimationFrame` for cancelling it.

To repeatedly call callback function, we should use it recursively.
``` jsx
function repeat(){
  // animation
   requestAnimationFrame(repeat);
}

requestAnimationFrame(repeat);
```