Travailleurs Web

Apprenez à exécuter du code JavaScript en arrière-plan à l'aide de Web Workers

introduction

JavaScript est à thread unique. Rien ne peut fonctionner en parallèle en même temps.

C'est génial car nous n'avons pas à nous soucier de tout un ensemble de problèmes qui se produiraient avec la programmation simultanée.

Avec cette limitation, le code JavaScript est obligé d'être efficace dès le départ, sinon l'utilisateur aurait une mauvaise expérience. Les opérations coûteuses doivent être asynchrones pour éviter de bloquer le thread.

Au fur et à mesure que les besoins des applications JavaScript augmentaient, cela a commencé à devenir un problème dans certains scénarios.

Les Web Workers introduisent la possibilité d'une exécution parallèle à l'intérieur du navigateur.

Ils ont quelques limitations:

  • pas d'accès auDOM: l'objet Window et l'objet Document
  • ils peuvent communiquer avec le programme JavaScript principal en utilisant la messagerie
  • ils doivent être chargés de la même origine (domaine, port et protocole)
  • ils ne fonctionnent pas si vous diffusez la page en utilisant le protocole de fichier (file://)

La portée globale d'un Web Worker, au lieu de Window qui se trouve dans le thread principal, est unWorkerGlobalScopeobjet.

Prise en charge du navigateur pour les Web Workers

Assez bien!

Browser support for web workers

Vous pouvez vérifier la prise en charge des Web Workers en utilisant

if (typeof Worker !== 'undefined') {
}

Créer un Web Worker

Vous créez un Web Worker en initialisant un objet Worker, en chargeant un fichier JavaScript de la même origine:

const worker = new Worker('worker.js')

Communication avec un Web Worker

Il existe deux manières principales de communiquer avec un Web Worker:

Utilisation de postMessage dans l'objet Web Worker

Vous pouvez envoyer des messages en utilisantpostMessagesur leWorkerobjet.

Important: un message est transféré, non partagé.

main.js

const worker = new Worker('worker.js')
worker.postMessage('hello')

worker.js

onmessage = event => {
  console.log(event.data)
}

onerror = event => { console.error(event.message) }

Renvoyer des messages

Un travailleur peut renvoyer des messages à la fonction qui l'a créé. en utilisant son globalpostMessage()fonction:

worker.js

onmessage = event => {
  console.log(event.data)
  postMessage('hey')
}

onerror = event => { console.error(event.message) }

main.js

const worker = new Worker('worker.js')
worker.postMessage('hello')

worker.onmessage = event => { console.log(event.data) }

Plusieurs écouteurs d'événements

Si vous souhaitez configurer plusieurs écouteurs pour lemessageévénement, au lieu d'utiliseronmessagecréer un écouteur d'événement (s'applique auerrorévénement aussi):

worker.js

addEventListener('message', event => {
  console.log(event.data)
  postMessage('hey')
}, false)

addEventListener(‘message’, event => { console.log(I'm curious and I'm listening too) }, false)

addEventListener(‘error’, event => { console.log(event.message) }, false)

main.js

const worker = new Worker('worker.js')
worker.postMessage('hello')

worker.addEventListener(‘message’, event => { console.log(event.data) }, false)

Utilisation de l'API Channel Messaging

Au lieu d'utiliser l'API postMessage intégrée offerte par les Web Workers, nous pouvons choisir d'utiliser le plus polyvalentAPI de messagerie de canalpour leur communiquer.

main.js

const worker = new Worker('worker.js')
const messageChannel = new MessageChannel()
messageChannel.port1.addEventListener('message', event => {
  console.log(event.data)
})
worker.postMessage(data, [messageChannel.port2])

worker.js

addEventListener('message', event => {
  console.log(event.data)
})

Un Web Worker peut renvoyer des messages en publiant un message àmessageChannel.port2, comme ça:

addEventListener('message', event => {
  event.ports[0].postMessage(data)
})

Cycle de vie du Web Worker

Les Web Workers sont lancés et s'ils ne restent pas en mode d'écoute pour les messages viaworker.onmessageou en ajoutant un écouteur d'événements, ils seront arrêtés dès que leur code sera exécuté jusqu'à la fin.

Un Web Worker peut être arrêté en utilisant sonterminate()méthode à partir du thread principal, et à l'intérieur du worker lui-même en utilisant la méthode globaleclose():

main.js

const worker = new Worker('worker.js')
worker.postMessage('hello')
worker.terminate()

worker.js

worker.onmessage = event => {
  console.log(event.data)
  close()
}

worker.onerror = event => { console.error(event.message) }

Chargement de bibliothèques dans un Web Worker

Les Web Workers peuvent utiliser leimportScripts()fonction globale définie dans leur portée globale:

importScripts('../utils/file.js', './something.js')

API disponibles dans Web Workers

Comme indiqué précédemment, le DOM n'est pas accessible par un Web Worker, vous ne pouvez donc pas interagir avec lewindowetdocumentobjets. Égalementparentest indisponible.

Vous pouvez cependant utiliser de nombreuses autres API, notamment:

Téléchargez mon gratuitManuel du débutant JavaScript


Plus de didacticiels sur le navigateur: