sql >> Base de Datos >  >> RDS >> Mysql

Desanidación de llamadas a la base de datos del nodo

Puede deshacerse de las llamadas a bases de datos anidadas usando promises .

Ya que mencionó que está usando mysql biblioteca para interactuar con la base de datos, desafortunadamente, esta biblioteca no proporciona una API basada en promesas. Entonces, para deshacerse de las llamadas a bases de datos anidadas en su código, debe crear un contenedor basado en promesas alrededor de la versión de devolución de llamada de las llamadas a bases de datos.

Para obtener una descripción general de qué son las promesas y cómo funcionan, consulte los siguientes enlaces:

El siguiente es un ejemplo de cómo puede crear un contenedor basado en promesas y luego usar ese contenedor para deshacerse de las llamadas de base de datos anidadas.

Este contenedor basado en promesas es solo una función que devuelve una promesa. Crea una instancia de promesa, envuelve la llamada a la base de datos subyacente y, finalmente, cuando la llamada a la base de datos devuelve los datos, notifica su código.

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);
       });
   });
}

Ahora en su función de controlador de ruta, en lugar de llamar a db.cats(...) , llama a esto getCats función contenedora.

Hay dos formas de llamar a la función que devuelve una promesa:

  • Promise-chaining (Para más detalles, visite los enlaces mencionados anteriormente)
  • async-await sintaxis (recomendado)

El siguiente ejemplo de código usa async-await sintaxis. Para esto, primero marque la función del controlador de ruta como async usando el async palabra clave antes de la function palabra clave. Haciendo esto, podemos usar await palabra clave dentro de esta función de controlador de ruta.

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
     }
});

El ejemplo de código anterior solo muestra cómo envolver db.cats(...) llame a la base de datos en un contenedor basado en promesas y use ese contenedor para obtener los datos de la base de datos. Del mismo modo, puede crear contenedores para db.dogs(...) y db.budgies(...) llamadas.

En lugar de crear un contenedor separado basado en promesas para cada llamada a la base de datos, idealmente, debe crear una función de contenedor reutilizable basada en promesas. que toma una función para llamar y envuelve esa llamada de función en una promesa tal como se muestra en el ejemplo de código anterior, es decir, getCats función.

Llamadas de bases de datos paralelas

Una cosa importante a tener en cuenta en el código anterior en la función de controlador de ruta

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

es que esto conducirá a llamadas secuenciales a la base de datos que puede o no ser lo que quieres.

Si estas llamadas a la base de datos no dependen unas de otras, puede llamar a los envoltorios basados ​​en promesas en paralelo usando Promise.all() método.

El siguiente ejemplo de código muestra cómo puede llamar a sus funciones contenedoras basadas en promesas en paralelo usando 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) {
       ...
     }
 });

Espero que esto sea suficiente para ayudarlo a deshacerse de las llamadas a bases de datos anidadas en su código actual y comenzar a usar promesas en su código.