Fermer

novembre 26, 2024

Le guide ultime de l’API Broadcast Channel

Le guide ultime de l’API Broadcast Channel


Dans cet article, nous explorerons l’API Broadcast Channel et son fonctionnement, ainsi que la manière dont elle peut être utilisée dans des cas réels.

Lors de l’utilisation d’une application Web, il est courant d’ouvrir plusieurs onglets de navigateur représentant différentes instances ou fenêtres de la même application. Ces transitions peuvent parfois entraîner une déconnexion entre les onglets du navigateur. Par exemple, vous pouvez vous déconnecter ou mettre à jour l’état de l’application dans un onglet, mais les autres peuvent toujours afficher que vous êtes connecté.

Parfois, actualiser la page peut résoudre le problème, mais ce n’est pas toujours la solution la plus efficace. Pour synchroniser plusieurs onglets du navigateur, les développeurs ont dû s’appuyer sur des techniques telles que les événements localStorage, les interrogations constantes, les techniciens de service, etc.

Contrairement à ces approches, le navigateur dispose d’une API Web intégrée appelée API Broadcast Channel, qui offre une solution efficace pour synchroniser les données entre les onglets, les fenêtres et les iframes en temps réel.

Dans cet article, nous explorerons l’API Broadcast Channel et son fonctionnement, ainsi que la manière dont elle peut être utilisée dans des cas réels.

Qu’est-ce que l’API du canal de diffusion ?

L’API Broadcast Channel permet une communication de base entre différents contextes de navigation, notamment les onglets, les fenêtres, les frames et les iframes, sur la même origine que l’application. Cela nous permet de créer un canal de communication simple qui peut être exploité, ce qui permet à tous les onglets ouverts ou autres contextes de rester facilement synchronisés.

Contrairement au window.postMessage méthode, l’API Broadcast Channel simplifie les choses en évitant d’avoir à gérer la fenêtre ou l’iframe cible séparément. Les cibles peuvent s’abonner à une chaîne existante en créant une nouvelle instance de canal de diffusion portant le même nom que la chaîne concernée.

Comment ça marche

L’élément central de l’API Broadcast Channel est le canal. Une fois créée, la chaîne peut diffuser des données vers tous les contextes (tels que les onglets, les fenêtres, etc.) qui sont abonnés à cette chaîne spécifique. Vous pouvez considérer le canal comme un système de sonorisation pour votre application, dans lequel tous les contextes abonnés peuvent entendre les messages transmis.

Canal de diffusion - un canal ou un canal pouvant transmettre des données

Toute instance d’une application particulière exécutée dans un contexte de navigateur peut toujours créer un canal de diffusion en créant une instance de la classe Broadcast Channel. Nous pouvons y parvenir en transmettant le nom du canal au constructeur de classe.

L’important ici est d’utiliser le même nom de canal de manière cohérente dans toutes les instances qui doivent être connectées. Après l’avoir configurée, cette instance peut commencer à diffuser des données sur le canal.

Instanciation d'un canal de diffusion : onglet du navigateur ou fenêtre postMessage au canal de diffusion

Les contextes destinataires peuvent également écouter et recevoir les données transmises.

Envoi et réception de données avec l'API du canal Broadcast : Même origine - l'onglet ou la fenêtre du navigateur A a postMessage, B et C ont chacun onMessage. Tous pointés vers Broadcast Channel

Sur la base de l’illustration ci-dessus, il est important de noter que lorsqu’une instance de l’application est visible dans une instance particulière. Le contexte A et les données sont transmis à travers le canal. Les autres contextes, B et C, ne peuvent qu’écouter à ce moment-là. De plus, lorsque le contexte B transmet, A et C peuvent écouter.

Compatibilité du navigateur

L’API Broadcast Channel est prise en charge dans les versions modernes et standard de Google Chrome, Mozilla Firefox, Microsoft Edge, Safari, Opera et Samsung Internet. L’API n’est prise en charge dans aucune version d’Internet Explorer ni dans les anciennes versions de Safari.

Pour que votre application continue de fonctionner correctement sur tous les navigateurs, il est important de mettre en place un mécanisme de détection des fonctionnalités. De cette façon, vous pouvez vérifier si l’API Broadcast Channel est disponible et, sinon, proposer une solution de secours.

Avantages de l’utilisation de l’API Broadcast Channel

L’API Broadcast Channel offre de nombreux avantages lorsque vous travaillez avec des applications Web modernes. En voici quelques-uns :

  • Synchronisation des données en temps réel: L’un des avantages les plus importants est la possibilité de synchroniser instantanément les données sur plusieurs contextes de navigateur, tels que les onglets, les fenêtres ou les iframes. Qu’il s’agisse de mettre à jour le statut de la session utilisateur, de synchroniser le panier de l’utilisateur, de gérer les notifications, etc., les modifications apportées à un onglet sont instantanément reflétées dans les autres.
  • Élimine la dépendance à l’égard d’un tiers: L’API Broadcast Channel est l’une des API Web fournies, ce qui signifie que nous n’avons pas besoin de recourir à des bibliothèques tierces ou à des services externes pour réaliser la synchronisation. Cela en fait une solution plus sécurisée, fiable et sans entretien.
  • Simplicité: L’API Broadcast Channel est légère et facile à configurer et à mettre en œuvre. Nous pouvons facilement créer un canal et commencer à transmettre des données avec seulement quelques lignes de code.
  • Expérience utilisateur améliorée: La synchronisation de plusieurs contextes de navigateur peut empêcher un comportement incohérent, améliorant ainsi l’expérience de l’utilisateur. Par exemple, un navigateur se déconnectant dans un onglet déconnecte automatiquement l’utilisateur de tous les onglets ouverts.
  • Demandes réseau réduites: Avec l’API Broadcast Channel, tout s’exécute localement dans le navigateur, éliminant ainsi le besoin de faire des requêtes réseau ou d’interroger constamment un serveur.

Implémentation de l’API du canal de diffusion

Comme mentionné précédemment, la mise en œuvre de l’API Broadcast Channel est simple et ne nécessite que quelques étapes. Dans cette section, nous passerons en revue les étapes de mise en œuvre de l’API Broadcast Channel, couvrant tout, de la création d’un canal à la gestion des messages et éventuellement à la déconnexion du canal lorsqu’il n’est plus nécessaire.

Créer ou rejoindre une chaîne de diffusion

Pour utiliser l’API Broadcast Channel, nous devons créer ou rejoindre une chaîne. Pour nous connecter à une chaîne de diffusion, nous devons créer une instance du canal par défaut BroadcastChannel classe et transmettez le nom du canal à son constructeur.

Si une instance d’une application effectue la première tentative de connexion à un canal de diffusion spécifique, le canal portant le nom défini est créé.

const channel = new BroadcastChannel("test_bc");

Ici, nous avons créé une chaîne de diffusion avec le nom test_bc.

Transmission de données

Une fois le canal créé, nous pouvons désormais transférer des données à travers celui-ci en utilisant le postMessage méthode de l’instance de canal de diffusion.

channel.postMessage("Sample text sent over the broadcast channel");

Ici, nous avons déclenché le postMessage méthode et passé quelques textes. La méthode peut également envoyer des nombres, des objets, des tableaux, ainsi que d’autres types de données non primitifs.

Recevoir un message

L’API Broadcast Channel fournit un onMessage méthode de réception de données du canal de diffusion. onMessage est un gestionnaire d’événements déclenché lorsque des données sont envoyées à partir de n’importe quel autre contexte sur le même canal, et il capture les données envoyées.

channel.onmessage = (event) => {
  console.log(event);
};

Ici, nous avons capturé et enregistré l’événement sur la console.

Déconnexion d’une chaîne de diffusion

Une fois que la communication inter-contextuelle n’est plus nécessaire, il est recommandé de se déconnecter du canal de diffusion. Nous pouvons utiliser le close méthode sur l’instance d’objet du canal de diffusion pour se déconnecter du canal.

channel.close();

Cela empêche la réception de nouveaux messages, libérant ainsi des ressources.

Cas d’utilisation

Dans la section précédente, nous avons vu comment implémenter l’API Broadcast Channel. Maintenant, faisons une démonstration dans une simple application Next.js.

Exécutez la commande ci-dessous dans votre terminal pour créer un projet Next.js :

npx create-next-app

Ensuite, entrez un nom pour le projet et acceptez les invites résultantes comme indiqué ci-dessous :

Configuration du projet

Accédez au dossier de projet nouvellement créé et démarrez le serveur de développement :

cd test-project
npm run dev

Remplacez le code dans le src/app/page.tsx fichier avec les éléments suivants :

import React from "react";

export default function Home() {
  return <div className="">hello world!</div>;
}

Une fois la configuration du projet terminée, faisons une démonstration de l’API avant d’examiner des cas d’utilisation individuels.

Créer un components/Demo.tsx fichier dans le src/ dossier et ajoutez-y ce qui suit :

"use client";

import { useEffect, useState } from "react";

export default function Demo() {
  const [message, setMessage] = useState("");
  const [receivedMessage, setReceivedMessage] = useState("");

  useEffect(() => {
    const channel = new BroadcastChannel("test_bc");

    channel.onmessage = (event) => {
      setReceivedMessage(event.data);
    };

    return () => {
      channel.close();
    };
  }, []);

  const sendMessage = () => {
    const channel = new BroadcastChannel("test_bc");
    channel.postMessage(message);
  };

  return (
    <div>
      <h2>Broadcast Channel API Demo</h2>
      <input
        type="text"
        value={message}
        onChange={(e) => setMessage(e.target.value)}
        placeholder="Type a message"
        className="border mr-4"
      />
      <button onClick={sendMessage}>Send Message</button>
      {receivedMessage && (
        <p>
          <span className="font-semibold">Received message:</span>{" "}
          {receivedMessage}
        </p>
      )}
    </div>
  );
}

Le code ci-dessus affiche un champ de saisie et un bouton. Le champ de saisie prend en compte les saisies de texte et le bouton, lorsqu’il est cliqué, déclenche un sendMessage fonction. La fonction configure la chaîne de diffusion et publie le texte saisi sur la chaîne.

Pour recevoir les données du canal, nous avons défini un useEffect crochet qui appelle le onMessage gestionnaire.

Ajoutez le composant au src/app/page.tsx fichier comme indiqué ci-dessous :

import React from "react";
import Demo from "@/components/Demo";

export default function Home() {
  return (
    <div className="m-8">
      <Demo />
    </div>
  );
}

Ouvrez l’application pour voir ce que nous avons.

Démo de l'API Broadcast Channel : l'utilisateur saisit un message dans le champ et clique sur Envoyer le message. Le message est envoyé et affiché dans un autre onglet. Le message reçu s'affiche. Et un nouveau message est renvoyé.

Vous pouvez voir comment l’état est synchronisé sur différents onglets sans avoir à actualiser la page.

Gestion des sessions utilisateur

Dans cette section, nous verrons comment l’API Broadcast Channel peut aider à gérer les sessions utilisateur sur plusieurs onglets ou fenêtres du navigateur.

Lorsqu’un utilisateur se connecte ou se déconnecte dans un onglet, tous les autres onglets doivent être automatiquement notifiés et mis à jour.

Créer un SessionProvider.tsx fichier dans le src/components/ dossier et ajoutez-y ce qui suit :

"use client";

import {
  createContext,
  useContext,
  useState,
  useEffect,
  ReactNode,
} from "react";

type Props = {
  children: ReactNode,
};

type ContextType = {
  isAuthenticated: boolean,
  login: () => void,
  logout: () => void,
};

const SessionContext = (createContext < ContextType) | (undefined > undefined);

export const useSession = (): ContextType => {
  const context = useContext(SessionContext);
  if (!context) {
    throw new Error("error");
  }
  return context;
};

export const SessionProvider = ({ children }: Props) => {
  const [isAuthenticated, setIsAuthenticated] =
    useState <
    boolean >
    (() => {
      return localStorage.getItem("auth") === "logged_in";
    });

  const login = () => {
    setIsAuthenticated(true);
    localStorage.setItem("auth", "logged_in");
    broadCastMsg("login");
  };

  const logout = () => {
    setIsAuthenticated(false);
    localStorage.removeItem("auth");
    broadCastMsg("logout");
  };

  const broadCastMsg = (message: string) => {
    const channel = new BroadcastChannel("session");
    channel.postMessage({ action: message });
    channel.close();
  };

  useEffect(() => {
    const channel = new BroadcastChannel("session");
    channel.onmessage = (event: MessageEvent) => {
      if (event.data.action === "logout") {
        setIsAuthenticated(false);
        localStorage.removeItem("auth");
      } else if (event.data.action === "login") {
        setIsAuthenticated(true);
        localStorage.setItem("auth", "logged_in");
      }
    };
    return () => channel.close();
  }, []);

  return (
    <SessionContext.Provider value={{ isAuthenticated, login, logout }}>
      {children}
    </SessionContext.Provider>
  );
};

Dans le code ci-dessus, nous avons d’abord créé un contexte et défini un SessionProvider composant d’ordre supérieur qui transmet le contexte aux composants enfants.

isAuthenticated est une valeur d’état booléenne qui indique si un utilisateur est authentifié ou non. login est une fonction qui met à jour le isAuthenticated état et conserve les données avec le stockage local du navigateur.

Nous avons ensuite défini un logout fonction qui met à jour l’état et appelle le broadcastMsg fonction. Le broadcastMsg La fonction gère la configuration du canal de diffusion de session et la transmission des données sur ce canal.

Ensuite, pour recevoir les données du canal de diffusion, nous avons défini un useEffect hook qui se connecte au canal de session et déclenche le onMessage gestionnaire d’événements, qui met à jour l’état en conséquence.

Enfin, nous avons défini le useSession hook qui peut être utilisé ailleurs dans l’application pour accéder aux données stockées dans le contexte.

Maintenant, créons une page d’authentification. Créer un src/app/auth/page.tsx fichier et ajoutez-y ce qui suit :

"use client";

import { useSession } from "@/components/SessionProvider";

export default function Home() {
  const { isAuthenticated, login, logout } = useSession();

  return (
    <div className="p-4 my-12 w-full max-w-[30rem] text-center border">
      <h1 className="text-2xl font-semibold">Auth page</h1>
      {!isAuthenticated && (
        <button onClick={login} className="my-4 underline text-green-900">
          Login
        </button>
      )}
      {isAuthenticated && (
        <>
          <p className="my-2">You are logged in!</p>
          <button onClick={logout} className="my-2 underline text-red-500">
            Logout
          </button>
        </>
      )}
    </div>
  );
}

Le code ci-dessus importe le useSession hook et met à jour la page en conséquence.

Nous devons également envelopper la page dans un fichier de mise en page avec le SessionProvider composant.

Créer un layout.tsx fichier dans le src/app/auth/ dossier et ajoutez-y ce qui suit :

import { SessionProvider } from "@/components/SessionProvider";

export default function AuthLayout({
  children,
}: {
  children: React.ReactNode,
}) {
  return <SessionProvider>{children}</SessionProvider>;
}

Ouvrez la route de la page d’authentification dans le navigateur pour prévisualiser la démo.

Gestion des sessions avec l'API Broadcast Channel - la connexion fonctionne sur plusieurs onglets

Vous pouvez également voir comment le statut d’authentification se synchronise entre les onglets.

Remplissage automatique de formulaire à plusieurs onglets

Un autre cas d’utilisation de l’API Broadcast Channel consiste à remplir automatiquement les données d’un formulaire dans plusieurs onglets ou fenêtres du navigateur. Si un utilisateur saisit des données dans un formulaire dans un onglet, cela devrait automatiquement se refléter dans les autres onglets ouverts.

Pour ce faire, créons un autre contexte de gestion et de synchronisation des données du formulaire. Créer un FormCtxProvider.tsx fichier dans le /src/components/ dossier et ajoutez-y ce qui suit :

"use client";

import { createContext, useContext, useState, useEffect, ReactNode } from 'react';

type Props = {
  children: ReactNode;
}

type FormContextType = {
  formData: { [key: string]: string };
  update: (field: string, value: string) => void;
}

const FormContext = createContext<FormContextType | undefined>(undefined);

export const useFormCtx = (): FormContextType => {
  const context = useContext(FormContext);
  if (!context) {
    throw new Error('error!');
  }
  return context;
};

export const FormCtxProvider = ({ children }: Props) => {
  const [formData, setFormData] = useState<{ [key: string]: string }>({
    username: '',
    email: '',
    hobby: ''
  });

  const update = (field: string, value: string) => {
    const updatedData = { ...formData, [field]: value };
    setFormData(updatedData);
    localStorage.setItem('formData', JSON.stringify(updatedData));
    broadcastData(field, value);
  };

  const broadcastData = (field: string, value: string) => {
    const channel = new BroadcastChannel('form_sync');
    channel.postMessage({ field, value });
    channel.close();
  };

  useEffect(() => {
    const storedFormData = localStorage.getItem('formData');

    if (storedFormData) {
      setFormData(JSON.parse(storedFormData));
    }

    const channel = new BroadcastChannel('form_sync');

    channel.onmessage = (event: MessageEvent) => {
      const { field, value } = event.data;
      setFormData(prevFormData => ({
        ...prevFormData,
        [field]: value
      }));
    };
    return () => channel.close();
  }, []);

  return (
    <FormContext.Provider value={{ formData, update }}>
      {children}
    </FormContext.Provider>
  );
};

Le code ci-dessus est similaire à celui que nous avons dans le SessionProvider composant du cas d’utilisation précédent. Nous avons:

  • mise à jour: Une fonction pour mettre à jour l’état et également conserver les données.
  • données de diffusion: Pour configurer le canal de diffusion et également transmettre des données.
  • utiliserEffet: pour écouter les mises à jour et refléter les modifications dans les onglets ou les fenêtres en conséquence.

Ensuite, créez un src/app/form/page.tsx fichier et ajoutez-y ce qui suit :

"use client";

import { ChangeEvent } from "react";
import { useFormCtx } from "@/components/FormCtxProvider";

export default function Form() {
  const { formData, update } = useFormCtx();

  const handleChange = (e: ChangeEvent<HTMLInputElement>) => {
    const { name, value } = e.target;
    update(name, value);
  };

  return (
    <form className="p-4 my-12 mx-4 w-full max-w-[30rem] border">
      <h1 className="text-2xl font-semibold text-center">
        Multi-tab form autofill
      </h1>
      <div className="w-full flex flex-col gap-2 my-4">
        <label>Name:</label>
        <input
          type="text"
          name="username"
          value={formData.username}
          onChange={handleChange}
          className="border p-2"
        />
      </div>

      <div className="w-full flex flex-col gap-2 my-4">
        <label>Email:</label>
        <input
          type="email"
          name="email"
          value={formData.email}
          onChange={handleChange}
          className="border p-2"
        />
      </div>

      <div className="w-full flex flex-col gap-2 my-4">
        <label>Hobby:</label>
        <input
          type="text"
          name="hobby"
          value={formData.hobby}
          onChange={handleChange}
          className="border p-2"
        />
      </div>
    </form>
  );
}

Dans le code ci-dessus, nous avons créé des champs de formulaire et les avons liés au formData état à partir du contexte défini. Le handleChange La fonction déclenche la mise à jour pour implémenter les modifications.

Ajoutons un layout.tsx fichier au src/app/form/ dossier et ajoutez-y ce qui suit :

import { FormCtxProvider } from "@/components/FormCtxProvider";

export default function FormLayout({
  children,
}: {
  children: React.ReactNode,
}) {
  return <FormCtxProvider>{children}</FormCtxProvider>;
}

Ici, nous avons enveloppé la page du formulaire avec notre FormCtxProvider.

Accédez à l’itinéraire du formulaire dans le navigateur et prévisualisez le formulaire. Remarquez comment les données saisies dans les entrées du formulaire persistent dans différents onglets.

Remplissage automatique de formulaires multi-onglets avec l'API Broadcast Channel - champs pour le nom, l'e-mail et le passe-temps - le formulaire est rempli de la même manière dans les différents onglets

Conclusion

L’API Broadcast Channel fournit une solution simple pour synchroniser plusieurs contextes sans solutions de contournement complexes. Bien qu’il existe de nombreux autres cas d’utilisation de l’API Broadcast Channel, nous n’en avons abordé que quelques-uns pour simplifier cet article.




Source link