Heim  >  Artikel  >  Web-Frontend  >  Klassische Techniken: Single-Threading und asynchrones JavaScript

Klassische Techniken: Single-Threading und asynchrones JavaScript

WBOY
WBOYnach vorne
2022-02-03 07:00:301980Durchsuche

Dieser Artikel vermittelt Ihnen relevantes Wissen über Single-Threading und Asynchronität in JavaScript. Ich hoffe, er wird Ihnen hilfreich sein.

Klassische Techniken: Single-Threading und asynchrones JavaScript

Als ich diesen Artikel schrieb, habe ich auch viele Artikel gelesen, aber die meisten davon waren sehr einfach und die konzeptionellen Dinge waren sehr vage, also habe ich nach einigen Kursen gesucht, sie mir angehört und mir hier ein paar Notizen gemacht Ich werde es für eine zukünftige Überprüfung kurz zusammenfassen ~

Prozesse und Threads

1. Bei einer Ausführung des Programms belegt es einen einzigartigen Speicherplatz – auf den Sie über Windows zugreifen können. Sehen Sie sich den Prozess an im Task-Manager;

: Es ist eine unabhängigeAusführungseinheit innerhalb des Prozesses; es ist die grundlegende Planungseinheit der CPU; 3. Die Beziehung zwischen Prozessen und Threads:

* Es gibt im Allgemeinen mindestens einen laufenden Thread in einem Prozess: Hauptthread

– automatisch erstellt, nachdem der Prozess gestartet wurde;

* Mehrere Threads können auch gleichzeitig ausgeführt werden ein Prozess, sagen wir: Das Programm ist multithreaded

* Daten innerhalb eines Prozesses können direkt von mehreren Threads geteilt werden * Daten zwischen mehreren Prozessen können nicht direkt geteilt werden

4 Oder mehrere Prozesse? => Prozess

6. Läuft der Browser Single-Threaded oder Multi-Threaded?

* Sie sind alle Multithreaded

Single-Threaded

1. Was ist Singlethreaded?

Ein Hauptmerkmal der JavaScript-Sprache ist, dass sie Single-Threaded ist, was bedeutet, dass sie jeweils nur eine Sache ausführen kann.

//栗子
console.log(1)
console.log(2)
console.log(3)
//输出顺序 1 2 3
2. Warum JavaScript Single-Threaded ist

Zunächst gibt es historische Gründe, warum Multiprozess- und Multithread-Architekturen nicht beliebt waren und die Hardwareunterstützung nicht gut war.

Zweitens erfordern Multithreading-Vorgänge aufgrund der Komplexität von Multithreading eine Sperre, und die Komplexität der Codierung wird zunehmen.

Das Letzte hängt mit seinem Zweck zusammen. Als Browser-Skriptsprache besteht der Hauptzweck von JavaScript darin, mit Benutzern zu interagieren und das DOM gleichzeitig ohne Multithreading zu betreiben Das Ergebnis des DOM-Renderings ist unvorhersehbar.

Um die Rechenleistung von Multi-Core-CPUs zu nutzen, schlägt HTML5 den Web Worker-Standard vor, der es JavaScript-Skripten ermöglicht, mehrere Threads zu erstellen, die untergeordneten Threads werden jedoch vollständig vom Haupt-Thread gesteuert und dürfen den nicht bedienen DOM. Daher ändert dieser neue Standard nichts an der Single-Threaded-Natur von JavaScript. 1. Synchrone Aufgaben/asynchrone Aufgaben von JS

Eine Aufgabe; 步 Alle synchronen Aufgaben werden im Hauptthread ausgeführt, um einen Ausführungskontextstapel zu bilden.


Asynchrone Aufgaben: Aufgaben, die außerhalb des Hauptthreads

ausgeführt werden; Es gibt auch eine „

Aufgabenwarteschlange

“ (Aufgabenwarteschlange) außerhalb des Hauptthreads. Wenn die asynchrone Aufgabe abgeschlossen ist, wird sie in der Form platziert Eine Rückruffunktion, die in der

Aufgabenwarteschlange

wartet. Wenn der Hauptthread inaktiv ist, geht der Hauptthread zur Ereigniswarteschlange, um die wartende Rückruffunktion herauszunehmen und zur Ausführung in den Hauptthread zu stellen. Dieser Prozess wird wiederholt ausgeführt, um den „Ereignisschleifenmechanismus“ (Ereignisschleife) von js zu bilden.

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

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

// 同步
console.log(3)

//输出顺序 1 3 2

2. Warum muss JavaScript asynchron sein
  • Wenn ein bestimmter Codeabschnitt während der Ausführung von JS-Code zu lange ausgeführt wird, wird der nachfolgende Code längere Zeit nicht ausgeführt, was zu einer
  • Blockierung
  • führt ( d. h. steckengeblieben), was sich auf die Benutzererfahrung auswirkt.
  • 3. So implementieren Sie Asynchronität in JavaScript
1) Ausführungsstapel und Aufgabenwarteschlange

Tatsächlich haben wir oben bereits erwähnt, dass JS asynchron über die
Ereignisschleife implementiert
  • 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. Alle Codes werden nach dem Parsen zum Ausführungsstapel hinzugefügt
  2. Execute (1), Makroaufgabe, Aufruf von webapi setTimeout, diese Methode fügt die Rückruffunktion nach 100 ms in die Aufgabenwarteschlange der Makroaufgabe ein
  3. Execute (2), das gleiche wie (1) ), aber es wird etwas später als (1) ausgeführt
  4. Führen Sie (3) aus, führen Sie das neue Versprechen synchron aus, führen Sie dann (4) aus, drucken Sie 3 direkt, dann lösen Sie auf (4), dann . then(), put (5) Geben Sie die Aufgabenwarteschlange
  5. der Mikrotask ein und führen Sie (6) wie oben aus. Drucken Sie zuerst 5, führen Sie dann Auflösung (6) aus und fügen Sie dann den Inhalt in .then() hinzu ( 8) in die Aufgabenwarteschlange der Mikroaufgabe
  6. execute (9), synchronisieren Sie den Code, drucken Sie direkt 7
  7. Execute (10), das gleiche wie (1) und (2), aber die Zeit ist kürzer, die Rückrufkonsole .log(8) wird nach 50 ms zur Aufgabenwarteschlange der Makroaufgabe hinzugefügt
  8. Jetzt ausführen Der Stapel wird geleert, die Mikroaufgabenwarteschlange wird überprüft und festgestellt, dass (5) zur Ausführung zum Ausführungsstapel hinzugefügt wird . Es handelt sich um einen synchronen Code, und 4 wird direkt erneut ausgeführt, die Mikrotask-Warteschlange wird erneut überprüft und (8) wird erneut gedruckt . Überprüfen Sie die Mikrotask-Warteschlange. Wenn sie zu diesem Zeitpunkt länger als 50 ms ist, werden Sie feststellen, dass sich console.log(8) in der Reihenfolge befindet 1 2
  9. Hinweis: Da es sich beim Rendern auch um eine Makroaufgabe handelt, muss das Rendern nach der Ausführung eines Ausführungsstapels ausgeführt werden. Wenn sich daher mehrere Codes im Ausführungsstapel befinden, die denselben Stil synchron ändern, rendern Sie nur den letzten eins.
  10. Verwandte Empfehlungen:
  11. Javascript-Lern-Tutorial

Das obige ist der detaillierte Inhalt vonKlassische Techniken: Single-Threading und asynchrones JavaScript. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:csdn.net. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen