Você pode se livrar de chamadas de banco de dados aninhadas usando
promete
. Como você mencionou que está usando
mysql
biblioteca para interagir com o banco de dados, infelizmente, esta biblioteca não fornece uma API baseada em promessa. Portanto, para se livrar de chamadas de banco de dados aninhadas em seu código, você precisa criar um wrapper baseado em promessa em torno da versão de retorno de chamada das chamadas de banco de dados. Para uma visão geral do que são promessas e como elas funcionam, veja os links a seguir:
A seguir está um exemplo de como você pode criar um wrapper baseado em promessa e, em seguida, usar esse wrapper para se livrar de chamadas de banco de dados aninhadas.
Esse wrapper baseado em promessa é apenas uma função que retorna uma promessa. Ele cria uma instância de promessa, envolve a chamada de banco de dados subjacente e, eventualmente, quando a chamada de banco de dados retorna os dados, notifica seu 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);
});
});
}
Agora em sua função de manipulador de rotas, em vez de chamar
db.cats(...)
, chame isso de getCats
função de encapsulamento. Existem duas maneiras de chamar a função que retorna uma promessa:
Encadeamento de promessas
(Para detalhes, visite os links mencionados acima)async-await
sintaxe (recomendado)
O exemplo de código a seguir usa
async-await
sintaxe. Para isso, primeiro marque a função do manipulador de rota como async
usando o assíncrono
palavra-chave antes da função
palavra-chave. Fazendo isso, podemos usar await
palavra-chave dentro desta função de manipulador de rota. 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
}
});
O exemplo de código acima mostra apenas como envolver o
db.cats(...)
chamada de banco de dados em um wrapper baseado em promessa e use esse wrapper para obter os dados do banco de dados. Da mesma forma, você pode criar wrappers para db.dogs(...)
e db.budgies(...)
chamadas. Em vez de criar um wrapper baseado em promessa separado para cada chamada de banco de dados, idealmente, você deve criar uma função wrapper baseada em promessa reutilizável que recebe uma função para chamar e envolve essa chamada de função em uma promessa como mostrado no exemplo de código acima, ou seja,
getCats
função. Chamadas de banco de dados paralelas
Uma coisa importante a ser observada no código acima na função do manipulador de rotas
const cats = await getCats();
const dogs = await getDogs();
const budgies = await getBudgies();
é que isso levará a chamadas sequenciais ao banco de dados que pode ou não o que você quer.
Se essas chamadas de banco de dados não dependerem umas das outras, você poderá chamar os wrappers baseados em promessas em paralelo usando
Promise.all()
método. O exemplo de código a seguir mostra como você pode chamar suas funções wrapper baseadas em promessa em 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 isso seja suficiente para ajudá-lo a se livrar das chamadas de banco de dados aninhadas em seu código atual e começar a usar promessas em seu código.