Home  >  Article  >  Web Front-end  >  Classic techniques: single-threading and asynchronous JavaScript

Classic techniques: single-threading and asynchronous JavaScript

WBOY
WBOYforward
2022-02-03 07:00:302035browse

This article brings you relevant knowledge about single-threading and asynchronousness in JavaScript. I hope it will be helpful to you.

Classic techniques: single-threading and asynchronous JavaScript

When writing this article, I also read many articles, but most of them were very simple and the conceptual things were very vague, so I looked for I listened to some courses and took some notes. I will briefly summarize them here for future review~

Processes and Threads

1. Process : Once the program is executed, it occupies a unique memory space ---- You can view the process through the Windows Task Manager;

2. Thread: It is an independent execution unit within the process; it is a complete process of program execution; the basic scheduling unit of the CPU;

3. The relationship between processes and threads:

* There is generally at least one running thread in a process: Main thread -- After the process is started Automatically created;

* Multiple threads can also be run in one process at the same time. We will say that the program is multi-threaded;

* Data within a process can For multiple threads to share directly;

* Data between multiple processes cannot be shared directly

4. Is the browser running a single process or multiple processes?

* Some are single processes

* firefox

* Some are multi-process

* chrome

5. How to check whether the browser is multi-process What process is running?

* Task Manager==>Process

6. Is the browser running single-threaded or not? Multi-threaded?

* They are all run by multi-threads


Single-threaded

1. What is single-threaded

A major feature of the JavaScript language is single-threading, which means that it can only do one thing at the same time.

//栗子
console.log(1)
console.log(2)
console.log(3)
//输出顺序 1 2 3

2. Why JavaScript is single-threaded

  • First of all, there are historical reasons. When the JavaScript language was created, multi-process and multi-thread architectures were not popular, and hardware support was not available. not good.
  • Secondly, because of the complexity of multi-threading, multi-threading operations require locking, and the complexity of coding will increase.
  • Finally, it is related to its purpose. As a browser scripting language, the main purpose of JavaScript is to interact with users and operate the DOM. If the DOM is operated at the same time, without locking in multiple threads, it will eventually lead to The results of DOM rendering are unpredictable.

In order to take advantage of the computing power of multi-core CPUs, HTML5 proposes the Web Worker standard, which allows JavaScript scripts to create multiple threads, but the child threads are completely controlled by the main thread and must not operate the DOM. Therefore, this new standard does not change the single-threaded nature of JavaScript.


Synchronization and asynchronous

1. JS synchronous tasks/asynchronous tasks

Synchronous tasks: in On the main thread The tasks queued for execution can only be executed after the first task is completed. All synchronization tasks are executed on the main thread Execute on the thread to form an

execution stack

(execution context stack).

Asynchronous tasks:

Tasks executed outside the main thread; outside the main thread, there is also a "task queue" (task queue ), when the asynchronous task is completed, it will be put into the task queue in the form of a callback function to wait. When the main thread is idle, the main thread will go to the event queue to take out the waiting callback function and put it into the main thread. executed in. This process is executed repeatedly to form the event loop mechanism (Event Loop) of js.

//栗子
// 同步
console.log(1)

// 异步
setTimeout(()=>{
    console.log(2)
},100)

// 同步
console.log(3)

//输出顺序 1 3 2
2. Why JavaScript needs to be asynchronous

If during the execution of JS code, a certain piece of code is executed for too long, the subsequent code will not be executed for a long time, resulting in

blocking

(i.e. stuck), which will affect the user experience. 3. How to implement asynchronous JavaScript

1) Execution stack and task queue

In fact, we have already mentioned above that JS implements asynchronous through

event loop

Let’s understand a few concepts first:

  • JS任务 分为同步任务(synchronous)和异步任务(asynchronous)
  • 同步任务都在 JS引擎线程(主线程) 上执行,形成一个执行栈(call stack)
  • 事件触发线程 管理一个 任务队列(Task Queue)
  • 异步任务 触发条件达成,将 回调事件 放到任务队列(Task Queue)中
  • 执行栈中所有同步任务执行完毕,此时JS引擎线程空闲,系统会读取任务队列,将可运行的异步任务回调事件添加到执行栈中,开始执行

 当一个JS文件第一次执行的时候,js引擎会 解析这段代码,并将其中的同步代码 按照执行顺序加入执行栈中,然后从头开始执行。如果当前执行的是一个方法,那么js会向执行栈中添加这个方法的执行环境,然后进入这个执行环境继续执行其中的代码。当这个执行环境中的代码 执行完毕并返回结果后,js会退出这个执行环境并把这个执行环境销毁,回到上一个方法的执行环境。这个过程反复进行,直到执行栈中的代码全部执行完毕。

栗子 

//(1)
console.log(1)

//(2)
setTimeout(()=>{
    console.log(2)
},100)

//(3)
console.log(3)
  1. 先解析整段代码,按照顺序加入到执行栈中,从头开始执行
  2. 先执行(1),是同步的,所以直接打印 1
  3. 执行(2),发现是 setTimeout,于是调用浏览器的方法(webApi)执行,在 100ms后将 console.log(2) 加入到任务队列
  4. 执行(3),同步的,直接打印 3
  5. 执行栈已经清空了,现在检查任务队列,(执行太快的话可能此时任务队列还是空的,没到100ms,还没有将(2)的打印加到任务队列,于是不停的检测,直到队列中有任务),发现有 console.log(2),于是添加到执行栈,执行console.log(2),同步代码,直接打印 2 (如果这里是异步任务,同样会再走一遍循环:-->任务队列->执行栈)

所以结果是 1 3 2;

注意:setTimeout/Promise等我们称之为任务源。而进入任务队列的是他们指定的回调;

2)宏任务(macro task)与微任务(micro task)

 上面的循环只是一个宏观的表述,实际上异步任务之间也是有不同的,分为 宏任务(macro task) 与 微任务(micro task),最新的标准中,他们被称为 task与 jobs

  • 宏任务有哪些:script(整体代码), setTimeout, setInterval, setImmediate, I/O, UI rendering(渲染)
  • 微任务有哪些:process.nextTick, Promise, Object.observe(已废弃), MutationObserver(html5新特性)

下面我们再详细讲解一下执行过程:

 执行栈在执行的时候,会把宏任务放在一个宏任务的任务队列,把微任务放在一个微任务的任务队列,在当前执行栈为空的时候,主线程会 查看微任务队列是否有事件存在。如果微任务队列不存在,那么会去宏任务队列中 取出一个任务 加入当前执行栈;如果微任务队列存在,则会依次执行微任务队列中的所有任务,直到微任务队列为空(同样,是吧队列中的事件加到执行栈执行),然后去宏任务队列中取出最前面的一个事件加入当前执行栈...如此反复,进入循环。

注意:

  • 宏任务和微任务的任务队列都可以有多个
  • 当前执行栈执行完毕时会立刻先处理所有微任务队列中的事件,然后再去宏任务队列中取出一个事件。同一次事件循环中,微任务永远在宏任务之前执行。
  • 不同的运行环境 循环策略可能有不同,这里探讨chrome、node环境

 栗子

//(1)
setTimeout(()=>{
    console.log(1)   // 宏任务
},100)

//(2)
setTimeout(()=>{
    console.log(2)  // 宏任务
},100)

//(3)
new Promise(function(resolve,reject){
    //(4)
    console.log(3)  // 直接打印
    resolve(4)
}).then(function(val){
    //(5)
    console.log(val); // 微任务
})

//(6)
new Promise(function(resolve,reject){
    //(7)
    console.log(5)   // 直接打印
    resolve(6)
}).then(function(val){
    //(8)
    console.log(val);  // 微任务
})

//(9)
console.log(7)  // 直接打印

//(10)
setTimeout(()=>{
    console.log(8) // 宏任务,单比(1)(2)宏任务早
},50)

 上面的代码在node和chrome环境的正确打印顺序是 3 5 7 4 6 8 1 2

下面分析一下执行过程:

  1. All codes are added to the execution stack after parsing
  2. Execution (1), macro task, call webapi setTimeout, this method will put the callback function into the task queue of the macro task after 100ms
  3. Execute (2), the same as (1), but a little later than (1)
  4. Execute (3), execute new Promise synchronously, then execute (4), print 3 directly, and then resolve(4), then .then(), put (5) into the task queue of the microtask
  5. Execute (6), the same as above, first print 5, then execute resolve(6), then .then( )The content inside (8) is added to the task queue of the microtask
  6. Execute (9), synchronize the code, directly print 7
  7. Execute (10), the same as (1) and (2) , but the time is shorter, the callback console.log(8) will be added to the task queue of the macro task after 50ms
  8. Now the execution stack is cleared, start checking the microtask queue, find (5), add to the execution Stack execution is a synchronous code. Directly print 4
  9. task queue and finish execution. Then check the microtask queue and find (8). Print 6
  10. task queue and finish execution again. Check the microtask. Queue, there is no task, then check the macro task queue. If it exceeds 50ms at this time, you will find that console.log(8) is in the macro task queue, so print 8
  11. and print 1 2
  12. in sequence.

Note: Because rendering is also a macro task, rendering needs to be executed after an execution stack has been executed. Therefore, if there are several codes that synchronously change the same style in the execution stack at the same time, only Render the last one.

Related recommendations: javascript learning tutorial

The above is the detailed content of Classic techniques: single-threading and asynchronous JavaScript. For more information, please follow other related articles on the PHP Chinese website!

Statement:
This article is reproduced at:csdn.net. If there is any infringement, please contact admin@php.cn delete