Nouveau : Datasets open source gratuits disponibles !Decouvrir →
🟨
Intermediaire 20 min JavaScript

Les Promises en JavaScript

Pourquoi Promises en JavaScript ?

Promises sont un élément crucial en JavaScript pour gérer les opérations asynchrones de manière plus efficace et intuitive. Dans une application moderne, beaucoup d'opérations se déroulent en arrière-plan, comme des appels à l'API, la lecture/écriture de fichiers, ou des requêtes réseau. Sans Promises, les développeurs auraient du recourir à des callbacks imbriqués (callback hell), ce qui rend le code difficile à lire et à maintenir.

Un cas d'usage concret est lorsqu'on souhaite récupérer des données depuis une API RESTful pour mettre à jour l'état d'une application. Sans Promises, on pourrait avoir quelque chose comme ceci :

// Callback hell : une API de données fictive
function fetchData(callback) {
  setTimeout(() => {
    callback(null, { data: 'Données récupérées' });
  }, 2000);
}

fetchData((error, result) => {
  if (error) {
    console.error(error);
  } else {
    console.log(result.data);
  }
});

Ce code est difficile à lire et maintenir, surtout s'il y a plusieurs niveaux de callbacks imbriqués. C'est là que entrent en jeu les Promises.

Prerequis

  • Connaissance de base de JavaScript (variables, fonctions, boucles, etc.)
  • Compréhension des objets et des fonctions fléchées
  • Familiarité avec le concept de setTimeout, setInterval, etc.

Outils à installer (versions)

  • Node.js (v12 ou plus récent)
  • Un éditeur de code moderne comme VSCode

Concepts fondamentaux

1. Ce qu'est une Promise ?

Une Promise est un objet qui représente l'achèvement d'une opération asynchrone et sa valeur finale, soit la réussite, soit l'échec.

// Création d'une Promise
const myPromise = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve('Opération réussie');
  }, 2000);
});

myPromise.then(result => {
  console.log(result); // 'Opération réussie'
}).catch(error => {
  console.error(error);
});

2. La méthode then()

La méthode then() est utilisée pour traiter la valeur d'une Promise résolue.

// Utilisation de then()
const myPromise = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve('Opération réussie');
  }, 2000);
});

myPromise.then(result => {
  console.log(result); // 'Opération réussie'
});

3. La méthode catch()

La méthode catch() est utilisée pour gérer les erreurs de la Promise.

// Utilisation de catch()
const myPromise = new Promise((resolve, reject) => {
  setTimeout(() => {
    reject('Opération échouée');
  }, 2000);
});

myPromise.then(result => {
  console.log(result);
}).catch(error => {
  console.error(error); // 'Opération échouée'
});

4. La méthode finally()

La méthode finally() est utilisée pour exécuter un code qui sera toujours exécuté, quel que soit le résultat de la Promise.

// Utilisation de finally()
const myPromise = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve('Opération réussie');
  }, 2000);
});

myPromise.then(result => {
  console.log(result);
}).catch(error => {
  console.error(error);
}).finally(() => {
  console.log('Opération terminée'); // Toujours exécuté
});

Mise en pratique : Projet fil rouge

Nous allons construire un petit gestionnaire de tâches asynchrone avec Promises. Voici le projet complet et fonctionnel :

Étape 1 : Création du fichier index.js

// index.js
const fs = require('fs').promises;

async function main() {
  try {
    // Lire les tâches depuis un fichier JSON
    const data = await fs.readFile('tasks.json', 'utf8');
    let tasks = JSON.parse(data);

    // Ajouter une nouvelle tâche
    const newTask = { id: Date.now(), title: 'Nouvelle tâche', completed: false };
    tasks.push(newTask);

    // Écrire les tâches à nouveau dans le fichier
    await fs.writeFile('tasks.json', JSON.stringify(tasks, null, 2));
    console.log('Tâche ajoutée avec succès');

    // Lire et afficher toutes les tâches
    const updatedData = await fs.readFile('tasks.json', 'utf8');
    tasks = JSON.parse(updatedData);
    console.log('Liste des tâches :', tasks);
  } catch (error) {
    console.error('Erreur lors de l\'opération sur les tâches:', error);
  }
}

main();

Étape 2 : Création du fichier tasks.json

// tasks.json
[]

Étape 3 : Exécution du script

node index.js

Ce script lit un fichier JSON contenant des tâches, ajoute une nouvelle tâche, et enregistre les modifications dans le même fichier.

Erreurs fréquentes et debugging

1. Erreur : TypeError: Cannot read property 'then' of undefined

Code incorrect :

const myPromise = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve('Opération réussie');
  }, 2000);
});

myPromise.then(result => {
  console.log(result);
});

Code correct :

Le code ci-dessus est correct et ne devrait pas générer d'erreur.

2. Erreur : SyntaxError: Unexpected token } in JSON at position 1

Code incorrect :

const data = await fs.readFile('tasks.json', 'utf8');
let tasks = JSON.parse(data);

Code correct :

const data = await fs.readFile('tasks.json', 'utf8');
let tasks = JSON.parse(data.trim()); // Ajout de trim()

3. Erreur : UnhandledPromiseRejectionWarning: Error: ENOENT: no such file or directory, open 'tasks.json'

Code incorrect :

const myPromise = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve('Opération réussie');
  }, 2000);
});

myPromise.then(result => {
  console.log(result);
});

Code correct :

Ajouter une gestion des erreurs de lecture du fichier :

const fs = require('fs').promises;

async function main() {
  try {
    const data = await fs.readFile('tasks.json', 'utf8');
    let tasks = JSON.parse(data);
    console.log(tasks);
  } catch (error) {
    if (error.code === 'ENOENT') {
      console.log('Le fichier n\'existe pas, on le crée.');
      await fs.writeFile('tasks.json', '[]');
    } else {
      console.error('Erreur lors de la lecture du fichier :', error);
    }
  }
}

main();

Pour aller plus loin

1. Async/Await

Async/Await est une syntaxe simplifiée pour travailler avec des Promises.

// Utilisation d'async/await
const fetchData = async () => {
  try {
    const response = await fetch('https://api.example.com/data');
    const data = await response.json();
    console.log(data);
  } catch (error) {
    console.error('Erreur lors de la récupération des données :', error);
  }
};

fetchData();

2. Chaining Promises

La chaîne des Promises permet d'effectuer une série d'opérations asynchrones en chaînant les méthodes then().

// Chaînage de Promises
const fetchData = () => {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve('Données récupérées');
    }, 2000);
  });
};

fetchData()
  .then(result => {
    console.log(result);
    return fetchData();
  })
  .then(secondResult => {
    console.log(secondResult);
  })
  .catch(error => {
    console.error(error);
  });

3. Promise.all()

La méthode Promise.all() permet d'exécuter plusieurs Promises simultanément et de traiter les résultats une fois toutes les Promises résolues.

// Utilisation de Promise.all()
const fetchUser = () => {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve('Utilisateur récupéré');
    }, 1000);
  });
};

const fetchPosts = () => {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve('Posts récupérés');
    }, 2000);
  });
};

Promise.all([fetchUser(), fetchPosts()])
  .then(results => {
    console.log(results); // ['Utilisateur récupéré', 'Posts récupérés']
  })
  .catch(error => {
    console.error(error);
  });

Défi pratique

Créez une application CLI pour gérer des notes. L'application devrait permettre d'ajouter, de lire et de supprimer des notes en utilisant des Promises.

node app.js add "Ma première note"
node app.js list
node app.js delete 1

Le code de l'application doit être complet et fonctionnel.

Besoin d'aide sur JavaScript ?

Besoin d'aide sur un projet technique ? Decrivez-le pour des conseils personnalises.

Recevoir des conseils

Questions frequentes

Qu'est-ce que les Promises en JavaScript?
Les Promises sont un objet qui représente l'achèvement (ou le rejet) d'une opération asynchrone et sa valeur résultante.
Comment utiliser une Promise?
Pour utiliser une Promise, vous créez une nouvelle instance de Promise en passant une fonction qui prend deux arguments : resolve et reject. Vous appelez resolve lorsque l'opération réussit et reject si elle échoue.
Qu'est-ce qu'une chaîne de Promises?
Une chaîne de Promises est le concept d'enchaîner plusieurs Promises pour exécuter des opérations asynchrones de manière séquentielle, où la réponse d'une Promise déclenche l'exécution de la suivante.

Pages liees

Chaque semaine, le meilleur de la tech francaise

Tendances, salaires, outils et opportunites — directement dans votre boite mail.

Gratuit. Desabonnement en un clic. Pas de spam.