Maison > interface Web > js tutoriel > Générateurs JavaScript : boostez votre code avec la puissance de pause !

Générateurs JavaScript : boostez votre code avec la puissance de pause !

Linda Hamilton
Libérer: 2024-12-30 22:29:11
original
995 Les gens l'ont consulté

JavaScript Generators: Supercharge Your Code with Pausing Power!

Les générateurs JavaScript sont plutôt sympas. Ce sont des fonctions normales, mais avec des super pouvoirs. Je les ai beaucoup utilisés ces derniers temps, et je dois dire qu'ils ont changé ma façon de penser le flux de contrôle dans mon code.

Commençons par les bases. Un générateur est une fonction qui peut être mise en pause et reprise. Il utilise la syntaxe function* et le mot-clé rendement. Voici un exemple simple :

function* countToThree() {
  yield 1;
  yield 2;
  yield 3;
}

const counter = countToThree();
console.log(counter.next().value); // 1
console.log(counter.next().value); // 2
console.log(counter.next().value); // 3
Copier après la connexion
Copier après la connexion

Vous voyez comment nous pouvons parcourir la fonction un rendement à la fois ? C'est la magie des générateurs.

Mais les générateurs peuvent faire bien plus que simplement compter. Ils sont parfaits pour créer des itérateurs personnalisés. Supposons que vous souhaitiez générer une séquence de Fibonacci :

function* fibonacci() {
  let [prev, curr] = [0, 1];
  while (true) {
    yield curr;
    [prev, curr] = [curr, prev + curr];
  }
}

const fib = fibonacci();
for (let i = 0; i < 10; i++) {
  console.log(fib.next().value);
}
Copier après la connexion
Copier après la connexion

Ce générateur continuera à produire des nombres de Fibonacci pour toujours. C'est une séquence infinie, mais nous calculons uniquement les valeurs dont nous avons besoin.

Cela nous amène à l'une des choses les plus intéressantes à propos des générateurs : l'évaluation paresseuse. Ils ne calculent les valeurs que lorsque nous les demandons. Cela peut être très efficace pour les grands ensembles de données ou les calculs complexes.

Regardons un exemple plus pratique. Supposons que vous construisiez un système de pagination pour un grand ensemble de données :

function* paginate(items, pageSize) {
  for (let i = 0; i < items.length; i += pageSize) {
    yield items.slice(i, i + pageSize);
  }
}

const allItems = Array.from({ length: 100 }, (_, i) => i + 1);
const pageSize = 10;
const pages = paginate(allItems, pageSize);

console.log(pages.next().value); // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
console.log(pages.next().value); // [11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
Copier après la connexion
Copier après la connexion

Ce générateur nous permet de récupérer des pages de données selon nos besoins, sans avoir à tout charger en mémoire en même temps.

Les générateurs brillent également en matière de programmation asynchrone. Ils peuvent donner au code asynchrone l’apparence et le comportement d’un code synchrone. Voici un exemple utilisant la bibliothèque co :

const co = require('co');

function* fetchUserData() {
  const user = yield fetchUser();
  const posts = yield fetchPosts(user.id);
  const comments = yield fetchComments(posts[0].id);
  return { user, posts, comments };
}

co(fetchUserData).then(result => {
  console.log(result);
}).catch(error => {
  console.error(error);
});
Copier après la connexion
Copier après la connexion

Ce code semble synchrone, mais il effectue en réalité trois appels asynchrones. Le générateur s'arrête à chaque rendement jusqu'à ce que la promesse soit résolue.

Les générateurs peuvent également être utilisés pour le multitâche coopératif. Vous pouvez créer plusieurs générateurs et basculer entre eux, simulant une exécution simultanée :

function* task1() {
  yield 'Start task 1';
  yield 'Middle of task 1';
  yield 'End task 1';
}

function* task2() {
  yield 'Start task 2';
  yield 'Middle of task 2';
  yield 'End task 2';
}

function run(tasks) {
  const iterations = tasks.map(task => task());
  while (iterations.length) {
    const [first, ...rest] = iterations;
    const { value, done } = first.next();
    if (!done) {
      console.log(value);
      iterations.push(first);
    }
    iterations.unshift(...rest);
  }
}

run([task1, task2]);
Copier après la connexion

Ce code alterne entre les deux tâches, exécutant chacune une étape à la fois.

Les générateurs sont également parfaits pour créer des machines à états. Chaque rendement peut représenter un état différent :

function* trafficLight() {
  while (true) {
    yield 'red';
    yield 'green';
    yield 'yellow';
  }
}

const light = trafficLight();
console.log(light.next().value); // red
console.log(light.next().value); // green
console.log(light.next().value); // yellow
console.log(light.next().value); // red
Copier après la connexion

Ce feu de circulation continuera à parcourir ses états indéfiniment.

Parlons maintenant de quelques techniques plus avancées. La délégation du générateur vous permet de céder le passage à un autre générateur :

function* innerGenerator() {
  yield 'inner 1';
  yield 'inner 2';
}

function* outerGenerator() {
  yield 'outer 1';
  yield* innerGenerator();
  yield 'outer 2';
}

const gen = outerGenerator();
console.log(gen.next().value); // outer 1
console.log(gen.next().value); // inner 1
console.log(gen.next().value); // inner 2
console.log(gen.next().value); // outer 2
Copier après la connexion

La syntaxe rendement* délègue à innerGenerator, renvoyant toutes ses valeurs avant de continuer avec externalGenerator.

La gestion des erreurs dans les générateurs mérite également d'être mentionnée. Vous pouvez lancer des erreurs dans un générateur en utilisant la méthode throw() :

function* errorGenerator() {
  try {
    yield 'Start';
    yield 'Middle';
    yield 'End';
  } catch (error) {
    console.error('Caught:', error);
    yield 'Error handled';
  }
}

const gen = errorGenerator();
console.log(gen.next().value); // Start
console.log(gen.throw(new Error('Oops!')).value); // Caught: Error: Oops!
                                                  // Error handled
Copier après la connexion

Cela permet des stratégies de gestion des erreurs assez sophistiquées.

Les générateurs peuvent également être utilisés pour implémenter des algorithmes de backtracking. Voici un exemple simple qui génère toutes les combinaisons possibles d'éléments :

function* countToThree() {
  yield 1;
  yield 2;
  yield 3;
}

const counter = countToThree();
console.log(counter.next().value); // 1
console.log(counter.next().value); // 2
console.log(counter.next().value); // 3
Copier après la connexion
Copier après la connexion

Ce générateur produira toutes les combinaisons à 2 éléments des éléments donnés.

Un domaine dans lequel les générateurs brillent vraiment est le traitement de grandes quantités de données. Vous pouvez créer des pipelines de traitement de données efficaces qui calculent uniquement ce qui est nécessaire. Voici un exemple qui traite un gros fichier ligne par ligne :

function* fibonacci() {
  let [prev, curr] = [0, 1];
  while (true) {
    yield curr;
    [prev, curr] = [curr, prev + curr];
  }
}

const fib = fibonacci();
for (let i = 0; i < 10; i++) {
  console.log(fib.next().value);
}
Copier après la connexion
Copier après la connexion

Ce générateur lit le fichier ligne par ligne, vous permettant de traiter des fichiers volumineux sans les charger entièrement en mémoire.

Les générateurs peuvent également être utilisés pour implémenter le modèle Observable. Voici une implémentation simple :

function* paginate(items, pageSize) {
  for (let i = 0; i < items.length; i += pageSize) {
    yield items.slice(i, i + pageSize);
  }
}

const allItems = Array.from({ length: 100 }, (_, i) => i + 1);
const pageSize = 10;
const pages = paginate(allItems, pageSize);

console.log(pages.next().value); // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
console.log(pages.next().value); // [11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
Copier après la connexion
Copier après la connexion

Ce générateur agit comme un observateur, traitant chaque donnée qu'il reçoit.

Une autre utilisation intéressante des générateurs consiste à créer des structures de contrôle personnalisées. Voici un exemple de fonction de nouvelle tentative qui utilise des générateurs :

const co = require('co');

function* fetchUserData() {
  const user = yield fetchUser();
  const posts = yield fetchPosts(user.id);
  const comments = yield fetchComments(posts[0].id);
  return { user, posts, comments };
}

co(fetchUserData).then(result => {
  console.log(result);
}).catch(error => {
  console.error(error);
});
Copier après la connexion
Copier après la connexion

Cette fonction de nouvelle tentative tentera la fonction donnée jusqu'à maxAttempts fois avant d'abandonner.

En conclusion, les générateurs sont une fonctionnalité puissante de JavaScript qui peut vous aider à écrire du code plus expressif, efficace et maintenable. Ils sont parfaits pour gérer des flux de contrôle complexes, gérer des opérations asynchrones et traiter de grands ensembles de données. Bien qu'ils puissent sembler un peu étranges au début, une fois que vous les maîtriserez, vous découvrirez toutes sortes de façons créatives de les utiliser dans vos projets. Alors n'hésitez plus, essayez les générateurs dans votre prochain projet JavaScript. Vous pourriez être surpris de voir à quel point ils peuvent simplifier votre code !


Nos créations

N'oubliez pas de consulter nos créations :

Centre des investisseurs | Vie intelligente | Époques & Échos | Mystères déroutants | Hindutva | Développeur Élite | Écoles JS


Nous sommes sur Medium

Tech Koala Insights | Epoques & Echos Monde | Support Central des Investisseurs | Mystères déroutants Medium | Sciences & Epoques Medium | Hindutva moderne

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

source:dev.to
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Derniers articles par auteur
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal