JS basic task management

task management

A major feature of JavaScript language is single thread, that is, it can only process one task at a time. In order to coordinate the behaviors of events, user interaction, scripts, UI rendering and network processing, and prevent the non blocking of the main thread, the scheme of (Event Loop) Event Loop is applied.

JavaScript processing tasks are constantly looping in waiting for tasks, executing tasks, hibernating and waiting for new tasks. This mechanism is also called event loop.

  • The tasks in the task queue are executed only after the tasks in the main thread are executed
  • When a new task arrives, it will be put into the queue, and the first in first execution strategy will be adopted to execute the tasks in the queue
  • For example, when multiple settimeouts arrive at the same time, they should be executed in turn

Tasks include script (overall code), setTimeout, setInterval, DOM rendering, DOM events, Promise, XMLHTTPREQUEST, etc

Principle analysis

Here is an example to analyze macro tasks and micro tasks in detail

console.log("wgchen");
setTimeout(function() {
  console.log("timer");
}, 0);

Promise.resolve()
.then(function() {
  console.log("promise1");
})
.then(function() {
  console.log("promise2");
});

console.log("blog.csdn");


1. Execute the first macro task script first, and then output

script start

2. Then execute the asynchronous macro task to setTimeout and put it into the macro task queue for execution
3. Then execute to promise Then micro task and put it into the micro task queue for execution
4. Then execute to the main code output

script end

5. All tasks of the main thread are completed
6. Traverse the micro task queue through the event loop and transfer the promise Then the micro task reads to the main thread for execution, and then outputs.

promise1

7. Then execute promse Then generates a new micro task and puts it into the micro task queue
8. Main thread task execution completed
9. The current event loop traverses the micro task queue, reads the promise 2 micro task, puts it into the main thread for execution, and then outputs it

promise2

10. Main thread task execution completed

11. At this time, the micro task queue has no tasks, and then read the setTimeout task from the macro task queue, add it to the main thread, and then output it.

setTimeout

Script loading

The engine will not render DOM when executing tasks, so if script is defined in front, it is necessary to execute the task before rendering dom. It is recommended to put script in front of the BODY end tag.

timer

The timer will be put into the asynchronous task queue, and it also needs to wait for the execution of the synchronous task.

6 ms execution is set below. If the main thread code executes for 10 ms, the timer will not execute until the main thread finishes executing.

The HTML standard stipulates that the minimum time cannot be less than 4 milliseconds. For some asynchronous operations, such as DOM operations, the minimum time is 16 milliseconds. In short, setting the time higher is better for performance.

setTimeout(func,6);

The following code will first output wgchen blog. csdn. Net and then output ycc

setTimeout(() => {
  console.log("ycc");
}, 0);
console.log("wgchen.blog.csdn.net");


This is a description of the timer. The logic of other asynchronous operations such as event and XMLHTTPREQUEST is the same

Micro task

Micro tasks are generally generated by user code. Micro tasks have higher execution priority than macro tasks Then is a typical micro task. The code executed when instantiating Promise is synchronous, so the callback function registered by then is asynchronous micro task.

The execution order of tasks is synchronization task, micro task and macro task, so the execution results below are 1, 2, 3 and 4

setTimeout(() => console.log(4));

new Promise(resolve => {
  resolve();
  console.log(1);
}).then(_ => {
  console.log(3);
});

console.log(2);

Let's look at the following slightly more complex task code

setTimeout(() => {
  console.log("timer");

  setTimeout(() => {
    console.log("timeout timeout");
  }, 0);

  new Promise(resolve => {
    console.log("settimeout Promise");
    resolve();
  }).then(() => {
    console.log("settimeout then");
  });

}, 0);

new Promise(resolve => {
  console.log("Promise");
  resolve();
}).then(() => {
  console.log("then");
});

console.log("wgchen");

Instance operation

progress bar

Although the following timers are timed for one second, they are also executed in turn according to the principle of first in first out

let i = 0;
setTimeout(() => {
  console.log(++i);
}, 1000);

setTimeout(() => {
  console.log(++i);
}, 1000);


The following is an example of a progress bar, where each number is executed in a task

<!DOCTYPE html>
<html>

<head>
  <meta charset="utf-8">
  <title>wgchen</title>
  <link rel="shortcut icon" href="#" />
</head>

<body>
  <style>
    body {
      padding: 30px;
    }
    #hd {
      height: 30px;
      background: yellowgreen;
      width: 0;
      text-align: center;
      font-weight: bold;
    }
  </style>
  <div id="hd"></div>
</body>

<script>
  function view() {
    let i = 0;
    (function handle() {
      hd.innerHTML = i + "%";
      hd.style.width = i + "%";
      if (i++ < 100) {
        setTimeout(handle, 20);
      }
    })();
  }
  view();
  console.log("The timer starts...");
</script>

</html>

Task decomposition

A relatively time-consuming task may cause the viewer to get stuck, so the task can be divided into multiple small tasks and executed in different steps. The following is a function of statistics. We will find that the running time is very long.

console.time("runtime");

function hd(num) {
  let count = 0;
  for (let i = 0; i <= num; i++) {
    count += i;
  }
  console.log(count);
  console.timeEnd("runtime");
}

let num=987654321;
hd(num);
console.log("wgchen.blog.csdn.net"); 
//You need to wait until the above execution is completed

Now divide the task into small pieces and put them into the task queue, so that the viewer will not get stuck and will not affect the execution of subsequent code.

console.time("runtime");
let count = 0;
let num = 987654321;

function hd() {
  for (let i = 0; i < 100000000; i++) {
    if (num <= 0) break;
    count += num--;
  }
  if (num > 0) {
    console.log(num);
    setTimeout(hd);
  } else {
    console.log(num);
    console.log(count);
  }
}
hd();
console.log("wgchen.blog.csdn.net"); //Show it immediately

It's a better choice to leave it to micro task processing

async function hd(num) {
  let res = await Promise.resolve().then(_ => {
    let count = 0;
    for (let i = 0; i < num; i++) {
      count += num--;
    }
    return count;
  });
  console.log(res);
}
hd(987654321);
console.log("wgchen.blog.csdn.net");

Keywords: Javascript Front-end

Added by Rik Peters on Thu, 10 Feb 2022 12:30:56 +0200