Mysql
 sql >> Base de données >  >> RDS >> Mysql

Désimbrication des appels de base de données Node

Vous pouvez vous débarrasser des appels de base de données imbriqués en utilisant promises .

Puisque vous avez mentionné que vous utilisez mysql bibliothèque pour interagir avec la base de données, malheureusement, cette bibliothèque ne fournit pas d'API basée sur les promesses. Donc, pour vous débarrasser des appels de base de données imbriqués dans votre code, vous devez créer un wrapper basé sur des promesses autour de la version de rappel des appels de base de données.

Pour un aperçu général de ce que sont les promesses et de leur fonctionnement, consultez les liens suivants :

Voici un exemple de la façon dont vous pouvez créer un wrapper basé sur des promesses, puis utiliser ce wrapper pour vous débarrasser des appels de base de données imbriqués.

Ce wrapper basé sur des promesses n'est qu'une fonction qui renvoie une promesse. Il crée une instance de promesse, encapsule l'appel de base de données sous-jacent et, éventuellement, lorsque l'appel de base de données renvoie les données, il notifie votre code.

function getCats() {
   return new Promise((resolve, reject) => {
       // make the database call
       db.cats((error, cats) => {
           // in case of an error, reject the promise by
           // calling "reject" function
           // Also pass the "error" object to the "reject" function
           // as an argument to get access to the error message 
           // in the code that calls this "getCats" function
           if (error) {
              reject(error);
              return;
           }
           
           // if there was no error, call "resolve" function
           // to resolve the promise. Promise will be resolved 
           // in case of successful database call
           // Also pass the data to "resolve" function
           // to access this data in the code that calls this
           // "getCats" function
           resolve(cats);
       });
   });
}

Maintenant dans votre fonction de gestionnaire d'itinéraire, au lieu d'appeler db.cats(...) , appelez ceci getCats fonction wrapper.

Il existe deux manières d'appeler la fonction qui renvoie une promesse :

  • Promise-chaining (Pour plus de détails, visitez les liens mentionnés ci-dessus)
  • async-await syntaxe (recommandé)

L'exemple de code suivant utilise async-await syntaxe. Pour cela, marquez d'abord la fonction de gestionnaire de route comme async en utilisant le async mot-clé avant la function mot-clé. En faisant cela, nous pouvons utiliser await mot-clé à l'intérieur de cette fonction de gestionnaire d'itinéraire.

app.get('/pets', async function(req, res, next) {
    try {
       const cats = await getCats();
       // similar wrappers for other database calls
       const dogs = await getDogs();
       const budgies = await getBudgies();
       
       // render the pub template, passing in the data
       // fetched from the database 
       ...

     catch (error) {
       // catch block will be invoked if the promise returned by
       // the promise-based wrapper function is rejected
       // handle the error appropriately
     }
});

L'exemple de code ci-dessus montre uniquement comment envelopper le db.cats(...) appel de base de données dans un wrapper basé sur des promesses et utilisez ce wrapper pour obtenir les données de la base de données. De même, vous pouvez créer des wrappers pour db.dogs(...) et db.budgies(...) appels.

Au lieu de créer un wrapper basé sur des promesses séparé pour chaque appel de base de données, idéalement, vous devriez créer une fonction wrapper basée sur des promesses réutilisable qui prend une fonction à appeler et enveloppe cet appel de fonction dans une promesse comme indiqué dans l'exemple de code ci-dessus, c'est-à-dire getCats fonction.

Appels parallèles à la base de données

Une chose importante à noter dans le code ci-dessus dans la fonction de gestionnaire d'itinéraire

const cats = await getCats();
const dogs = await getDogs();
const budgies = await getBudgies();

est que cela conduira à des appels séquentiels de base de données qui peut ou non ce que vous voulez.

Si ces appels de base de données ne dépendent pas les uns des autres, vous pouvez appeler les wrappers basés sur des promesses en parallèle en utilisant Promise.all() méthode.

L'exemple de code suivant montre comment vous pouvez appeler vos fonctions wrapper basées sur des promesses en parallèle à l'aide de Promise.all() .

app.get('/pets', async function(req, res, next) {
    try {
       // "petsData" will be an array that will contain all the data from 
       // three database calls.
       const petsData = await Promise.all([getCats(), getDogs(), getBudgies()]);
       
       // render the pub template, passing in the data
       // fetched from the database 
       ...
 
     catch (error) {
       ...
     }
 });

J'espère que cela suffira pour vous aider à vous débarrasser des appels de base de données imbriqués dans votre code actuel et à commencer à utiliser des promesses dans votre code.