L'API Channel Messaging

L'API Channel Messaging permet aux iframes et aux workers de communiquer avec le fil de discussion principal du document, en passant des messages

Introduction à l'API Channel Messaging

Étant donné deux scripts exécutés dans le même document, mais dans un contexte différent, l'API Channel Messaging leur permet de communiquer en passant des messages via un canal.

Ce cas d'utilisation implique une communication entre

  • le document et une iframe
  • deux iframes
  • deux documents

Comment ça fonctionne

Appelnew MessageChannel()un canal de message est initialisé.

const channel = new MessageChannel()

Le canal a 2 propriétés, appelées

  • port1
  • port2

Ces propriétés sont un objet MessagePort.port1est le port utilisé par la partie qui a créé le canal, etport2est le port utilisé par le récepteur du canal (au fait, le canal est bidirectionnel, de sorte que le récepteur peut également renvoyer des messages).

À chaque extrémité du canal, vous écoutez sur un port et vous envoyez des messages à l'autre port.

L'envoi du message se fait via le

otherWindow.postMessage()

méthode, oùotherWindowest l'autre contexte de navigation.

Il accepte un message, une origine et le port.

Par exemple:

const data = { name: 'Flavio' }
const channel = new MessageChannel()
window.postMessage(data, [channel.port2])

Un message peut être l'une de ces valeurs prises en charge:

«Origin» est un URI (par exemplehttps://example.org). Vous pouvez utiliser'*'pour permettre une vérification moins stricte, ou spécifier un domaine, ou spécifier'/'pour définir une cible de même domaine, sans avoir besoin de spécifier de quel domaine il s'agit.

L'autre contexte de navigation écoute le message à l'aide dumessageun événement:

self.addEventListener('message', event => {
  console.log('A new message arrived!')
})

selféquivaut à utiliserwindowdans ce cas

Dans le gestionnaire d'événements, nous pouvons accéder aux données envoyées en regardant ledatapropriété de l'objet événement:

self.addEventListener('message', event => {
  console.log('A new message arrived!')
  console.log(event.data)
})

Nous pouvons répondre en utilisantMessagePort.postMessage:

self.addEventListener('message', event => {
  console.log('A new message arrived!')
  console.log(event.data)

const data = { someData: ‘hey’ } event.ports[0].postMessage(data) })

Un canal peut être fermé en invoquant leclose()méthode sur le port:.

self.addEventListener('message', event => {
  console.log('A new message arrived!')
  console.log(event.data)

const data = { someData: ‘hey’ } event.ports[0].postMessage(data) event.ports[0].close() })

Un exemple avec une iframe

Voici un exemple de communication entre un document et uniframeintégré dedans.

Le document principal définit uniframeet unspanoù nous imprimerons un message envoyé depuis leiframedocument. Aussi tôt que leiframele document est chargé, nous lui envoyons un message sur lechannelnous avons créé.

<!DOCTYPE html>
<html>
  <body>
    <iframe src="iframe.html" width="500" height="500"></iframe>
    <span></span>
  </body>
  <script>
    const channel = new MessageChannel()
    const display = document.querySelector('span')
    const iframe = document.querySelector('iframe')
<span style="color:#a6e22e">iframe</span>.<span style="color:#a6e22e">addEventListener</span>(<span style="color:#e6db74">'load'</span>, () =&gt; {
  <span style="color:#a6e22e">iframe</span>.<span style="color:#a6e22e">contentWindow</span>.<span style="color:#a6e22e">postMessage</span>(<span style="color:#e6db74">'Hey'</span>, <span style="color:#e6db74">'*'</span>, [<span style="color:#a6e22e">channel</span>.<span style="color:#a6e22e">port2</span>])
}, <span style="color:#66d9ef">false</span>)

<span style="color:#a6e22e">channel</span>.<span style="color:#a6e22e">port1</span>.<span style="color:#a6e22e">onmessage</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">event</span> =&gt; {
  <span style="color:#a6e22e">display</span>.<span style="color:#a6e22e">innerHTML</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">event</span>.<span style="color:#a6e22e">data</span>
}

</script> </html>

La source de la page iframe est encore plus simple:

<!DOCTYPE html>
<html>
  <script>
  window.addEventListener('message', event => {
    // send a message back
    event.ports[0].postMessage('Message back from the iframe')
  }, false)
  </script>
</html>

Comme vous pouvez le voir, nous n'avons même pas besoin d'initialiser un canal, car lewindow.onmessageLe gestionnaire est automatiquement exécuté lorsque le message est reçu de la page conteneur.

L'événement envoyé est composé des propriétés suivantes:

  • data: l'objet qui a été envoyé depuis l'autre fenêtre
  • origin: l'URI d'origine de la fenêtre qui a envoyé le message
  • source: l'objet window qui a envoyé le message

Vérifiez toujours l'origine de l'expéditeur du message.

e.ports[0]est la façon dont nous référenconsport2dans l'iframe, carportsest un tableau, et le port a été ajouté comme premier élément.

Un exemple avec un technicien de service

Un Service Worker est un worker piloté par les événements, un fichier JavaScript associé à une page Web. VérifiezGuide des travailleurs des servicespour en savoir plus sur eux.

Ce qu'il est important de savoir, c'est que les techniciens de service sont isolés du fil de discussion principal et que nous devons communiquer avec eux à l'aide de messages.

Voici comment un script joint au document principal gérera l'envoi de messages au Service Worker:

// `worker` is the service worker already instantiated

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

Dans le code Service Worker, nous ajoutons un écouteur d'événements pour lemessageun événement:

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

Et il peut renvoyer des messages en publiant un message àmessageChannel.port2, avec

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

Prise en charge du navigateur

L'API Channel Messaging est actuellement prise en charge par tous les principaux navigateurs, dont beaucoup depuis longtemps, de sorte que même les versions plus anciennes la prennent en charge. Découvrez tous les détails surhttps://caniuse.com/#feat=channel-messaging.

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


Plus de didacticiels sur le navigateur: