A directory

What’s the difference between a free front end and a salted fish

directory
A directory
The preface
Three single-thread and multi-thread
Four Event Loop
 4.1 Event Loop Process
 4.2 requestAnimationFrame
  2 requestAnimationFrame introduction
  4.2.2 Why requestAnimationFrame is used
 4.3 Web Worker
  4.3.1 Using Web workers
  4.3.2 Web Worker data communication
  4.3.3 Web Worker operable API
  4.3.4 Web Worker Compatibility
 4.4 Node and browser
5. Comparison of two environment Event loops
Six Question Training
 6.1 Synchronization Task
 6.2 timer
 6.3 Timer + Promise
 6.4 comprehensive
Vii References
 7.1 requestAnimationFrame Reference
 7.2 Web Worker References
 7.3 Other references

The preface

Returns the directory

An Event Loop is a mechanism in a browser or Node that allows JavaScript to run in a single thread without blocking, and is often used asynchronously.

Three single-thread and multi-thread

Returns the directory

JavaScript is a single-threaded language.

Single thread in program execution, the path of the program in sequential order, the first must be processed before the next can be executed.

In Chrome, for example, when you open a Tab, you create a process.

There can be multiple threads in a process, such as rendering threads, JS engine threads, HTTP request threads, and so on.

When you make a request, you create a thread that can be destroyed when the request ends.

  • What is the browser kernel?

The browser kernel is multi-threaded, and threads work together to keep in sync under the control of the kernel. A browser usually consists of the following resident threads:

  1. GUI rendering threads: parsing HTML, CSS, etc. While the JavaScript engine thread runs the script, the GUI rendering thread is suspended, that is, “frozen.”
  2. JavaScript engine threads: Responsible for processing JavaScript scripts.
  3. Timing trigger thread:setTimeout,setIntervalAnd so on. The event-triggering thread will add the event after counting to the end of the task queue, waiting for the JS engine thread to execute.
  4. Event trigger thread: responsible for handing prepared events to the JS engine for execution.
  5. asynchronoushttpRequest thread: the thread responsible for executing functions such as asynchronous requests, for examplePromise.then(),ajaxAnd so on.
  • Why not multithreading?

Let’s say I have A DOM node, and now I have thread A operating on it, deleting the DOM;

And then thread B goes back to it and modifies some part of the DOM.

So now the question is, who do we listen to?

So simply design a single thread, safe and secure.

Even if HTML5 produces a Web Worker in the later stage, it is not allowed to operate the DOM structure, and some distributed computing can be completed.

Web Workers are covered in this article

  • Why asynchrony?

Then there’s the problem. If we get stuck calling an Ajax interface or loading an image, will the page never render?

And since the single thread can only let the previous program finish first, even if the interface or image is slowed down, I still have other tasks to do, so I’m stuck.

So this is where asynchrony comes in:

When it comes to waiting for something to happen, we just let the program run.

Wait for the interface or image to come back and tell the program that I’m done and you can continue calling.

Four Event Loop

Returns the directory

  • Why are there Event loops?

As Jsliang mentioned earlier, JavaScript threads can only do one thing at a time.

If you run into programs that need to wait, such as setTimeout, then you’re done.

So JavaScript creates an Event Loop to coordinate events, user interactions, scripting, rendering, networking, and so on.

  • What is an Event Loop?

JavaScript reads from a script and then loops through the process of executing an Event from a “task queue”, known as an Event Loop.

4.1 Event Loop Process

Returns the directory

The Event Loop execution process is as follows:

  1. Start the whole scriptscriptExecute as a macro task
  2. During the execution, the synchronized code is executed directly, and the macro task enters the macro task queue and the micro task enters the micro task queue.
  3. Check the list of micro tasks after the current macro task is executed, and execute them successively until all the tasks are completed.
  4. Execution browserUIThread rendering work.
  5. Check if there areWeb WorkerTask, if there is to execute.
  6. After executing the macro task in this round, go back to Step 2 and repeat the process until the macro task and microtask queues are empty.

There are two types of asynchronous queues in an event loop: MacroTask and MicroTask.

Web workers are JS running in the background, independent of other scripts, and do not affect page performance.

There can be multiple macro task queues and only one microtask queue.

Macro tasks include:

  • script
  • setTimeout
  • setInterval
  • setImmediate
  • I/O
  • UI rendering

Microtasks include:

  • MutationObserver
  • Promise.then()/catch()
  • In order toPromiseOther technologies developed for the foundation, e.gfetch API
  • V8 garbage collection process
  • Unique to the Nodeprocess.nextTick

4.2 requestAnimationFrame

Returns the directory

2 requestAnimationFrame introduction

Returns the directory

Tell the browser window. RequestAnimationFrame () – you want to perform an animation, and required the browser until the next redraw calls the specified callback function to update the animation.

This method takes as an argument a callback function that is executed before the browser’s next redraw.

RequestAnimationFrame is short for rAF.

Let’s take a look at its use:

<body>
  <div class="animation">Animated elements</div>

  <script>
    window.onload = function() {
      const element = document.querySelector('.animation'); 
      let start;

      function step(timestamp) {
        if (start === undefined) {
          start = timestamp;
        }
        const elapsed = timestamp - start;

        Math.min() is used here to make sure the element stops at exactly 200px.
        element.style.transform = 'translateX(' + Math.min(0.1 * elapsed, 200) + 'px)';

        // Stop animation after two seconds
        if (elapsed < 2000) {
          window.requestAnimationFrame(step); }}window.requestAnimationFrame(step);
    };
  </script>
</body>
Copy the code

4.2.2 Why requestAnimationFrame is used

Returns the directory

If we use setTimeout to implement animation effects, we will find stutter and jitter on some low-end machines, which is caused by:

  • setTimeoutExecution events are not deterministic. It belongs to the macro task queue, and only when the task on the main thread is finished, the task in the queue will be called to determine whether to start the execution.
  • The refresh frequency is affected by the screen resolution and screen size, so the refresh frequency is different for different devices, whilesetTimeoutOnly one time interval can be fixed.

In the process of the Event Loop above, we know that there will be a step after executing the microtask queue:

  • Execution browserUIThread rendering work.

The requestAnimationFrame executes here and does not wait for the macro task queue to queue up, causing problems such as stalling.

4.3 Web Worker

Returns the directory

Web workers provide an easy way for Web content to run scripts in background threads.

As we all know, JavaScript has always been a single-threaded environment, and we can’t run two JavaScript scripts at the same time.

But imagine if we could run two (or more) JavaScript scripts at the same time, one to handle the UI interface (the way it’s always been used) and one to handle some complex computation, and performance would be better.

In the new SPECIFICATION of HTML5, Web Worker is implemented to introduce the “multi-threading” technology of JavaScript. Its ability allows us to load and run one or more separate JavaScript threads in the main JavaScript thread of the page.

Note: JavaScript is still single-threaded in nature, and Web workers are just a powerful API provided by browsers (hosted environments).

4.3.1 Using Web workers

Returns the directory

Calling the Web Worker:

index.js

console.log('index- Synchronization task ');
Promise.resolve().then((res) = > {
  console.log('index-Promise');
});
setTimeout(() = > {
  console.log('index-setTimeout');
}, 1000);
Copy the code

index.html

<script>
  window.onload = function() {
    console.log('Local - Sync Task');
    // Between microtasks
    Promise.resolve().then((res) = > {
      console.log('Local - Microtask 1');
    })
    const worker1 = new Worker('./index.js');
    Promise.resolve().then((res) = > {
      console.log('Local - Microtask 2');
    })

    // Between macro tasks
    setTimeout(() = > {
      console.log('Local - Macro Task 1');
    }, 1000);
    const worker2 = new Worker('./index.js');
    setTimeout(() = > {
      console.log('Local - Macro Task 2');
    }, 1000);
  };
</script>
Copy the code

Print the result when executing:

Local - Synchronization task Local - micro task 1 Local - micro task 2 index- Synchronization task index-Promise index- Synchronization task index-Promise Local - macro task 1 Local - macro task 2 index-setTimeout index-setTimeoutCopy the code

You can see:

  1. To perform firstscriptMedium synchronization task
  2. To performscriptIn the micro tasks
  3. Then perform the UI thread rendering work (this is not reflected in the code, you can try to add if you are interestedrAF)
  4. And then execute itWeb WorkerThe content inside
  5. Then theindex.htmlMacro task in
  6. The last isWeb WorkerMacro tasks in files

You can see that it still conforms to the Event Loop process.

4.3.2 Web Worker data communication

Returns the directory

index.js

onmessage = (res) = > {
  // Worker receives data
  console.log('Worker receives data: ', res);
  // Worker receives data:
  // MessageEvent {isTrusted: true, data: "check, here is index.html!" , origin: "", lastEventId: "", source: null... }

  // the Worker sends data
  postMessage('open the door! Here is the index. The js');
}
Copy the code

index.html

<script>
window.onload = function() {
  // instantiate Worker
  const worker = new Worker('./index.js');

  // index.html receives data
  worker.addEventListener('message'.(res) = > {
  console.log('index.html received data: ', res);
  // index.html received data:
  // MessageEvent {isTrusted: true, data: "open! Js ", origin: "", lastEventId: "", source: null,... }
  });

  // index.html sends data
  worker.postMessage('Round, this is index.html! ');

  / / terminate the Worker
  worker.terminate();
};
</script>
Copy the code

In index.html, pass:

  • worker.addEventListener('message', callback). Receive data passed by the Web Worker.
  • worker.postMessage('xxx'). Send data to the Web Worker.
  • worker.terminate(). Termination of the communications

In index.js, pass:

onmessage = (res) = > {
  console.log(res); // Accept data in the onmessage method
  postMessage('xxx'); // Send data via postMessage
}
Copy the code

4.3.3 Web Worker operable API

Returns the directory

  • SetTimeout (), clearTimeout(), setInterval(), clearInterval(): With these functions, you can use theWeb WorkerTimed operation performed in thread;
  • XMLHttpRequestObject: means we can be inWeb WorkerThread executionAjaxRequests;
  • navigatorObject: AvailableppName.appVersion.platform.userAgentInformation such as;
  • locationObject (read only) : Can get information about the current URL;

If you need to load other JS scripts:

importScripts('./index2.js'.'./index3.js');

/ / or

// importScripts('./index2.js');
// importScripts('./index3.js');
Copy the code

4.3.4 Web Worker Compatibility

Returns the directory

  • IE: Version 11
  • Edge: Version 14+
  • Firefox: version 51+
  • Chrome: version 56+
  • Others: See the Caniuse link

4.4 Node and browser

Returns the directory

Why are there browser Event loops and Node.js Event loops?

In a nutshell:

  • Your pages are displayed in the browser and your data is processed in the background. Is there any difference between the two? !

A little more carefully:

  • Node.js: Node. JsEvent LoopIs based onlibuv.libuvNode.jsEvent LoopThe implementation is made.
  • The browser: browser-basedEvent LoopIs based onHTML 5 specification. The HTML5 specification only defines the browserEvent LoopThe implementation is left to browser vendors.

Libuv is a multi-platform support library for asynchronous I/O. It was originally developed for Node.js and is now used by Luvit, Julia, Pyuv, and other frameworks. Github-libuv repository

Therefore, we need to distinguish these two Event loops. They are different things

5. Comparison of two environment Event loops

Returns the directory

In the browser environment, the microTask queue is executed after each MacroTask has been executed.

In Node.js, microTasks are executed between phases of the event cycle, i.e. tasks in the MicroTask queue are executed after each phase is completed.

Jsliang is not familiar with Node.js. The second reason is that the interviewer basically answered the browser’s Event Loop mechanism when asked, and occasionally mentioned the Event Loop is divided into browser Event Loop and Node Event Loop.

Six Question Training

Returns the directory

Before training, let’s talk about the scope of the exam questions:

  • Synchronous task: encounter direct execution, do not care.
  • Macro task:script,setTimeout
  • Micro tasks:Promise.then(),async/await

So much content for the moment, want to not be wrong!

6.1 Synchronization Task

Returns the directory

function bar() {
  console.log('bar');
}

function foo() {
  console.log('foo');
  bar();
}

foo();
Copy the code

What does this output?

  • foo -> bar

Details need not be explained.

6.2 timer

Returns the directory

console.log("1");

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

setTimeout(function () {
  console.log("3");
}, 2000);

console.log("4");
Copy the code
  • Macro task queue:script,setTimeout(2),setTimeout(3)
  • Microtask queue: none

So output:

1 2 3 4Copy the code

6.3 Timer + Promise

Returns the directory

  • Topic 1: Please print the following code
console.log('script start');

setTimeout(function() {
  console.log('setTimeout');
}, 0);

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

console.log('script end');
Copy the code

Script macro task:

  • Macro tasksetTimeout
  • Micro tasks.then(promise1)

Script start -> script end

Then invoke the microtask, output promisE1, and put THEN (promise2) into the microtask.

Call the microtask again and print promise2.

Finally, the macro task setTimeout is called and setTimeout is printed.

So the output order:

script start
script end
promise1
promise2
setTimeout
Copy the code

  • Topic 2: Please print the following code
Promise.resolve().then(function promise1() {
  console.log('promise1');
})

setTimeout(function setTimeout1() {
  console.log('setTimeout1')
  Promise.resolve().then(function promise2() {
    console.log('promise2'); })},0)

setTimeout(function setTimeout2() {
  console.log('setTimeout2')},0)
Copy the code

Script macro task:

  • Synchronization task: None
  • Micro tasks:Promise.then(promise1)
  • Macro task:setTimeout(setTimeout1),setTimeout(setTimeout2)

So go to sync task first, find no, ignore.

Then the microtask promise. then(promise1) outputs promise1.

SetTimeout (setTimeout1) :

  • Synchronization task:console.log('setTimeout1')
  • Micro tasks:Promise.then(promise2)
  • Macro task:setTimeout(setTimeout2)(Note that the macro task is holistic.)

So go ahead with the synchronization task and print setTimeout1.

Then go microtask and export Promise2.

Then the macro task setTimeout(setTimeout2) is introduced.

The setTimeout(setTimeout2) environment does not have any microtasks or macros, so when the synchronization task is finished, the output setTimeout2 is finished.

Therefore, the output order:

promise1
setTimeout1
promise2
setTimeout2
Copy the code

  • Topic 3: Please print the following code
setTimeout(function() {
  console.log(4);
}, 0);

const promise = new Promise((resolve) = > {
  console.log(1);
  for (var i = 0; i < 10000; i++) {
    i == 9999 && resolve();
  }
  console.log(2);
}).then(function() {
  console.log(5);
});

console.log(3);
Copy the code

Under the script:

  • Synchronization task:console.log(1),console.log(2),console.log(3).
  • Micro tasks:Promise.then()(Wait until 9999 to add)
  • Macro tasksetTimeout

So let’s go to the sync task first, and note that when we new Promsie(), the internal code will execute, just like the sync task, while.then() will be added to the microtask in the resolve() case.

So print 1 -> 2 -> 3 first.

Then the microtask promise.then () is rolled out, so output 5.

Finally, the macro task setTimeout is introduced, which outputs 4.

The order of results is:

One, two, three, five, fourCopy the code

6.4 comprehensive

Returns the directory

Comprehensive questions will not give the answer to the analysis, please imagine.


  • Topic 1: Please print the following code
setTimeout(function () {
  console.log('timeout1');
}, 1000);

console.log('start');

Promise.resolve().then(function () {
  console.log('promise1');
  Promise.resolve().then(function () {
    console.log('promise2');
  });
  setTimeout(function () {
    Promise.resolve().then(function () {
      console.log('promise3');
    });
    console.log('timeout2')},0);
});

console.log('done');
Copy the code

Results:

start
done
promise1
promise2
timeout2
promise3
timeout1
Copy the code

  • Topic 2: Please print the following code
console.log("script start");

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

setTimeout(function() {
  console.log("setTimeout---200");
  setTimeout(function() {
    console.log("inner-setTimeout---0");
  });
  Promise.resolve().then(function() {
    console.log("promise5");
  });
}, 200);

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

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

console.log("script end");
Copy the code

Output:

script start
script end
promise1
promise3
promise2
setTimeout---0
setTimeout---200
promise5
inner-setTimeout---0
Copy the code

  • Topic 3: Please print the following code
console.log(1);

setTimeout(() = > {
  console.log(2);

  new Promise((resolve) = > {
    console.log(3);
  }).then(() = > {
    console.log(4);
  });
}, 200);

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

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

setTimeout(() = > {
  console.log(8);

  new Promise(function (resolve) {
    console.log(9);
    resolve();
  }).then(() = > {
    console.log(10);
  });
}, 100);

new Promise(function (resolve) {
  console.log(11);
  resolve();
}).then(() = > {
  console.log(12);
});

console.log(13);
Copy the code

Output:

1 5 11 13 12 7 8 9 10 2 3Copy the code

Vii References

Returns the directory

  • What is the difference between browser and Node Event loops?【 Reading Suggestions: 20min】
  • Learn the Event Loop once (Once and for all)【 Reading Suggestions: 20min】
  • The whole event loop thing【 Reading Suggestions: 10min】
  • An in-depth understanding of the JS event loop mechanism (Node.js)[Reading Suggestions: None]
  • Explain the Event Loop mechanism in JavaScript【 Reading Suggestions: 5min】
  • Understand JavaScript Event Loop in depth【 Reading Suggestions: 20min】
  • 【THE LAST TIME】 Thoroughly understand JavaScript execution mechanics【 Reading Suggestions: 20min】
  • JavaScript: Understand Synchronous, asynchronous, and Event loops inside out【 Reading Suggestions: 10min】
  • Explore javaScript asynchrony and browser update rendering timing from the Event Loop specification【 Reading Suggestions: 20min】
  • Tasks, microtasks, queues and schedules[Reading Suggestions: None]
  • The Node.js Event Loop, Timers, and process.nextTick()[Reading Suggestions: None]

7.1 requestAnimationFrame Reference

Returns the directory

  • Let’s talk about Promise, setTimeout, rAF, rIC【 Reading Suggestions: 10min】
  • window.requestAnimationFrame【 Reading Suggestions: 10min】

7.2 Web Worker References

Returns the directory

  • Multithreading in JavaScript – Web Workers[Recommended Reading: 30min]
  • Talk about HTML5 Web Workers【 Reading Suggestions: 10min】
  • JavaScript performance tool – Web Worker【 Reading Suggestions: 10min】

7.3 Other references

Returns the directory

  • Browser processes? Thread? Silly silly can’t tell!【 Reading Suggestions: 5min】

Jsliang’s document library is licensed by Junrong Liang under the Creative Commons Attribution – Non-commercial – Share alike 4.0 International License. Based on the github.com/LiangJunron… On the creation of works. Outside of this license agreement authorized access can be from creativecommons.org/licenses/by… Obtained.