RequestAnimationFrame is used in the Canvas animation article, discarking the traditional setInterval

setInterval

To run a piece of code repeatedly at fixed intervals.

requestAnimationFrame

A modern version of setInterval(); Executes the specified block of code before the browser next redraws the display, allowing the animation to run at the appropriate frame rate regardless of the environment in which it is running. What are the similarities? Both exist as asynchrony in Javascript single threads.

Javascript single-threaded

Processes and threads

Processes are like a factory (GPU) workshop, and the workers in the workshop are threads. Each workshop operates independently and workers work cooperatively. 1. A process contains multiple threads and the memory space of the process is shared by threads. 2. A process is the smallest unit assigned by the operating system, and a thread is the smallest unit of program execution

Threads in the browser

Timer thread

The browser timer counter is a separate thread that triggers periodic behavior and then enters the event trigger thread. If you are in a javascript thread, the count will be inaccurate because of blocking.

Event trigger thread

When an event (mouse click, Ajax request, timer, etc.) is triggered, it is added to the queue to be processed by the counting JS thread.

Asynchronous HTTP request threads

The browser has a separate thread for handling Ajax requests, and when there is a callback, the event triggers the thread

Javascript thread

Responsible for parsing and executing javascript scripts

GUI rendering thread

Select the HTML in your browser and the corresponding redraw. The GUI is temporarily suspended while the javascript thread runs the script

Event Loop Event Loop mechanism

My initial understanding is:

Synchronous tasks are executed on the JS thread, forming an execution stack; Callbacks in setTimeout, setInterval, and requestAnimationFrame act as asynchronous tasks in JS and are put into an event queue by firing the corresponding thread. After the content in the execution stack is executed, THE GPU will redraw, and then the JS engine will read the content in the event queue through the system and put the content in the execution stack.

What about in the actual process?

During an event loop, the result returned by an asynchronous event is placed in an event queue. Asynchronous events are grouped into macro and micro task queues based on their type. The execution stack executes the macro task first. When the macro task is empty, the main thread will check whether the current micro task has an event. If not, it will execute the next macro task.



Asynchronous Task Description.event-loop. Macro tasks in browsers mainly include timers and IO operations, while microtasks include Promise, Async and requestAnimationFrame, which are triggered as special tasks after the execution of microtasks.MDNTell the browser that you want to execute an animation and ask the browser to call the specified callback to update the animation before the next redraw.

First, a simple example:

document.body.style = 'background:blue'
console.log(1)
new Promise(res=>{
  document.body.style = 'background:gray'
  console.log(2)
  res(2)
}).then((r)=>{
  console.log(r)
  document.body.style = 'background:black'
})
console.log(3)
setTimeout(() => {
  console.log(4)
  document.body.style = 'background:pink'
}, 10)
Copy the code

Console final effect 1, 2, 3, 2, 4. 1. The color of the content in the macro task becomes blue. 2. Print 2 5. Print 3 6. Perform the print in the microtask promise returns result 2 7. Color black 8.GPU render 9. Execute new macro tasks 10. Print 4 11. The browser is going to look like the black is going to be pink, and it’s going to ignore the third step, because the microtask hasn’t finished yet, so it’s going to go straight to black when it redraws and let’s look at a more complicated example

console.log(1) setTimeout(() => { console.log('setTimeout') }, 10); new Promise((res,rej)=>{ res(11) console.log("Promise") }).then(res=>{ console.log(res+"PromiseThen") }).catch(rej=>{ })  window.requestAnimationFrame(()=>{ console.log('requestAnimationFrame') }) console.log("hah") let aa = new Promise((res,rej)=>{ res(2) }) async function bb() { let a = await aa; try { console.log(a+"try") } catch (error) { console.log(a+"catch") } } bb() console.log("end")Copy the code

The command output is as follows: 1—-Promise—-hah—-end—-11PromiseThen port 2try requestAnimationFrame password setTimeout the execution order is 1. The macro task starts printing 1 2. Triggers the timer thread and puts the callback into the event queue 3. Promise Prints the promise and puts the promise’s callback into the current microtask 4. Print HAH 5. Proceed with the promise and put the callback into the microtask 6. Print end 7. Perform the current micro task by printing console.log(res+”PromiseThen”) to print 11PromiseThen 8. To perform the current microtask, print console.log(a+”try”) to print 2try 9. Perform requestAnimationFrameconsole. Log (‘ requestAnimationFrame) print requestAnimationFrame 10. 11 GUP rendering. Execute console.log(‘setTimeout’) in the timer for the next macro task to print setTimeout