fromEvent() - convertit un événement en Observable
fromEvent()` est une Creation Function qui convertit les sources d'événements tels que les événements DOM et les EventEmitter de Node.js en flux Observable.
Vue d'ensemble.
FromEvent()` permet au traitement asynchrone basé sur les événements d'être géré dans le pipeline RxJS. Il enregistre automatiquement les auditeurs d'événements lorsqu'ils sont abonnés et supprime automatiquement les auditeurs lorsqu'ils sont désabonnés, réduisant ainsi de manière significative le risque de fuites de mémoire.
Signature :.
function fromEvent<T>(
target: any,
eventName: string,
options?: EventListenerOptions | ((...args: any[]) => T)
): Observable<T>Documentation officielle : 📘 RxJS formula : fromEvent()
Utilisation de base.
C'est l'exemple le plus simple pour traiter les événements DOM comme Observable.
import { fromEvent } from 'rxjs';
const clicks$ = fromEvent(document, 'click');
clicks$.subscribe(event => {
console.log('Bouton cliqué.:', event);
});
// Un événement est émis à chaque fois qu'il est cliqué.Caractéristiques importantes.
1. enregistrement et désenregistrement automatique des auditeurs
La fonction fromEvent() enregistre les auditeurs d'événements lorsqu'ils sont abonnés et supprime automatiquement les auditeurs lorsqu'ils sont désabonnés.
import { fromEvent } from 'rxjs';
const clicks$ = fromEvent<MouseEvent>(document, 'click');
const subscription = clicks$.subscribe(event => {
console.log('Position du clic:', event.clientX, event.clientY);
});
// 5Désabonné après quelques secondes (l'auditeur de l'événement est également supprimé automatiquement)
setTimeout(() => {
subscription.unsubscribe();
console.log('Désabonné');
}, 5000);function fromEvent<T>(
target: any,
eventName: string,
options?: EventListenerOptions | ((...args: any[]) => T)
): Observable<T>Prévention des fuites de mémoire
Lorsque vous appelez
unsubscribe(), unremoveEventListener()interne est automatiquement exécuté. Cela élimine le besoin de supprimer manuellement les écouteurs et réduit considérablement le risque de fuites de mémoire.
2. Observable à froid (chaque abonnement enregistre un écouteur indépendant).
L'Observable créé par fromEvent() est un **Cold Observable. Chaque abonnement enregistre un écouteur d'événement indépendant.
import { fromEvent } from 'rxjs';
const clicks$ = fromEvent(document, 'click');
// Abonné à1 - AuditeurAS'abonner à
clicks$.subscribe(() => console.log('Observer 1: Cliquer'));
// 1S'abonner en quelques secondes2Ajouter - AuditeurBS'enregistrer indépendamment de
setTimeout(() => {
clicks$.subscribe(() => console.log('Observer 2: Cliquer'));
}, 1000);
// 1Les deux récepteurs se déclenchent en un seul clic
// Cela prouve que chaque abonnement a des récepteurs indépendants.import { fromEvent } from 'rxjs';
const clicks$ = fromEvent(document, 'click');
clicks$.subscribe(event => {
console.log('Bouton cliqué.:', event);
});
// Un événement est émis à chaque fois qu'il est cliqué.**Preuve de froid Observable
Un nouvel écouteur d'événements est enregistré chaque fois qu'un abonnement est effectué et supprimé lorsque l'abonnement est désabonné. Il s'agit d'une caractéristique de Cold Observable. Cependant, il possède également la propriété Hot selon laquelle "les événements ne peuvent pas être reçus avant l'abonnement" parce que la source de l'événement (par exemple, les éléments DOM) est externe et partagée.
Prise en charge des types TypeScript
Les types d'événements peuvent être explicitement spécifiés.
import { fromEvent } from 'rxjs';
const input = document.createElement('input');
input.type = 'text';
document.body.appendChild(input);
const input$ = fromEvent<InputEvent>(input, 'input');
input$.subscribe(event => {
// eventLe type de laInputEvent
const target = event.target as HTMLInputElement;
console.log('Valeur d'entrée:', target.value);
});4. Observable à froid.
Le fromEvent() est un **Cold Observable. Chaque abonnement initie une exécution indépendante.
import { fromEvent } from 'rxjs';
const button = document.createElement('button');
button.innerText = "Abonné à";
document.body.appendChild(button);
const clicks$ = fromEvent(document, 'click');
// 1Le deuxième abonnement - Des auditeurs d'événements sont ajoutés
clicks$.subscribe(() => console.log('AbonnementA'));
// 2Le deuxième abonnement - Un autre récepteur d'événements est ajouté
clicks$.subscribe(() => console.log('AbonnementB'));
// 1Un clic déclenche les deux récepteurs
// Sortie:
// AbonnementA
// AbonnementBimport { fromEvent } from 'rxjs';
const clicks$ = fromEvent(document, 'click');
clicks$.subscribe(event => {
console.log('Bouton cliqué.:', event);
});
// Un événement est émis à chaque fois qu'il est cliqué.Caractéristiques Observables à froid Chaque abonnement démarre une exécution indépendante Chaque abonné reçoit son propre flux de données
Pour plus d'informations, voir Cold Observable et Hot Observable.
Cas d'utilisation pratiques.
1. gérer les événements de clic
Contrôler les clics sur les boutons et empêcher les clics consécutifs.
import { fromEvent } from 'rxjs';
import { debounceTime, map } from 'rxjs';
const button = document.createElement('button');
button.innerText = "submit";
document.body.appendChild(button);
const clicks$ = fromEvent(button, 'click');
clicks$.pipe(
debounceTime(300), // 300msIgnorer les clics consécutifs à l'intérieur de
map(() => 'pendant la transmission...')
).subscribe(message => {
console.log(message);
// APIAppels et autres processus
});2. validation en temps réel des entrées de formulaire
Flux d'événements de saisie et validation en temps réel.
import { fromEvent } from 'rxjs';
import { map, debounceTime, distinctUntilChanged } from 'rxjs';
const label = document.createElement('label');
label.innerText = 'email: ';
const emailInput = document.createElement('input');
label.appendChild(emailInput);
document.body.appendChild(label);
const email$ = fromEvent<InputEvent>(emailInput, 'input');
email$.pipe(
map(event => (event.target as HTMLInputElement).value),
debounceTime(500), // après l'arrêt de l'entrée.500msTraitement ultérieur
distinctUntilChanged() // Uniquement lorsque la valeur change
).subscribe(email => {
console.log('Soumis à validation:', email);
// Processus de validation des adresses électroniques
validateEmail(email);
});
function validateEmail(email: string): void {
const isValid = /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);
console.log(isValid ? 'Adresse électronique valide' : 'Adresse électronique non valide');
}Mise en œuvre du glisser-déposer
Combinez les événements de la souris pour mettre en œuvre le glisser-déposer.
import { fromEvent } from 'rxjs';
import { switchMap, takeUntil, map } from 'rxjs';
// Créer des éléments déplaçables
const element = document.createElement('div');
element.style.width = '100px';
element.style.height = '100px';
element.style.backgroundColor = '#333';
element.style.position = 'absolute'; // Positionnement absolu
element.style.left = '50px'; // Position initiale
element.style.top = '50px';
element.style.cursor = 'move'; // Curseur glissant
document.body.appendChild(element);
const mousedown$ = fromEvent<MouseEvent>(element, 'mousedown');
const mousemove$ = fromEvent<MouseEvent>(document, 'mousemove');
const mouseup$ = fromEvent<MouseEvent>(document, 'mouseup');
mousedown$.pipe(
switchMap(startEvent => {
// Enregistrement de la position du clic dans l'élément
const startX = startEvent.clientX - element.offsetLeft;
const startY = startEvent.clientY - element.offsetTop;
return mousemove$.pipe(
map(moveEvent => ({
left: moveEvent.clientX - startX,
top: moveEvent.clientY - startY
})),
takeUntil(mouseup$) // Se termine lorsque la souris est relevée
);
})
).subscribe(({ left, top }) => {
// Mise à jour de la position de l'élément
element.style.left = `${left}px`;
element.style.top = `${top}px`;
});4. surveiller les événements de défilement
Utilisé pour suivre le défilement infini et la position du défilement.
function fromEvent<T>(
target: any,
eventName: string,
options?: EventListenerOptions | ((...args: any[]) => T)
): Observable<T>Utilisation dans le pipeline.
fromEvent()` est idéal pour le traitement en pipeline à partir d'un flux d'événements.
Erreurs courantes.
1. oublier de se désinscrire
❌ Erreur - l'oubli de se désinscrire provoque des fuites de mémoire
function fromEvent<T>(
target: any,
eventName: string,
options?: EventListenerOptions | ((...args: any[]) => T)
): Observable<T>✅ Correct - toujours se désabonner
WARNING
Attention fuites de mémoire
Dans les SPA et les frameworks basés sur des composants, il faut toujours se désinscrire lorsque l'on détruit un composant. Si vous oubliez de vous désinscrire, les auditeurs d'événements resteront en place et provoqueront des fuites de mémoire.
2. enregistrement en double de plusieurs auditeurs d'événements
❌ Erreur - le fait de s'abonner plusieurs fois au même événement entraîne l'enregistrement de plusieurs auditeurs.
function fromEvent<T>(
target: any,
eventName: string,
options?: EventListenerOptions | ((...args: any[]) => T)
): Observable<T>✅ Correct - multicast avec share() si nécessaire.
Considérations sur les performances.
Les performances doivent être prises en compte lorsqu'il s'agit d'événements de déclenchement à haute fréquence (défilement, déplacement de la souris, redimensionnement, etc.)
TIP
Optimisation des événements à haute fréquence :.
throttleTime()- ne traiter qu'une fois tous les un certain laps de temps.debounceTime()- Traiter après l'arrêt de l'entrée.distinctUntilChanged()- Ne traiter que lorsque la valeur change.
❌ Problèmes de performance - traitement à chaque redimensionnement
function fromEvent<T>(
target: any,
eventName: string,
options?: EventListenerOptions | ((...args: any[]) => T)
): Observable<T>✅ Optimisation - traitement une fois toutes les 200 ms
Fonctions de Creation Function pertinentes.
Résumé
- fromEvent()` convertit les événements DOM et EventEmitter en Observable
- Listener enregistré lors de l'abonnement, automatiquement supprimé lors du désabonnement (évite les fuites de mémoire)
- Fonctionne comme un Observable chaud
- Toujours effectuer le désabonnement pour éviter les fuites de mémoire
- Optimise les événements à haute fréquence avec
throttleTime()etdebounceTime().