Du kan bli av med kapslade databasanrop genom att använda code>löften .
Eftersom du nämnde att du använder mysql
biblioteket för att interagera med databasen, tyvärr tillhandahåller detta bibliotek inte ett löftesbaserat API. Så för att bli av med kapslade databasanrop i din kod måste du skapa ett löftesbaserat omslag runt återuppringningsversionen av databasanrop.
För en allmän översikt över vad löften är och hur de fungerar, se följande länkar:
Nedan följer ett exempel på hur du kan skapa ett löftesbaserat omslag och sedan använda det omslaget för att bli av med kapslade databasanrop.
Detta löftesbaserade omslag är bara en funktion som returnerar ett löfte. Den skapar en löftesinstans, avslutar det underliggande databasanropet och så småningom när databasanropet returnerar data, meddelar den din kod.
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);
});
});
}
Nu i din rutthanterarfunktion, istället för att anropa db.cats(...)
, kalla detta getCats
omslagsfunktion.
Det finns två sätt du kan anropa funktionen som returnerar ett löfte:
Löftekedja
(För mer information, besök länkarna som nämns ovan)async-await
syntax (rekommenderas)
Följande kodexempel använder async-await
syntax. För detta, markera först rutthanterarens funktion som async
genom att använda async
nyckelord före funktionen
nyckelord. Genom att göra detta kan vi använda await
nyckelord i denna rutthanterarfunktion.
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
}
});
Ovanstående kodexempel visar bara hur man lindar db.cats(...)
databasanrop i ett löftesbaserat omslag och använd det omslaget för att hämta data från databasen. På samma sätt kan du skapa omslag för db.dogs(...)
och db.budgies(...)
samtal.
Istället för att skapa en separat löftesbaserad omslag för varje databasanrop, bör du helst skapa en återanvändbar löftesbaserad omslagsfunktion som tar in en funktion för att anropa och omsluter det funktionsanropet i ett löfte precis som visas i ovanstående kodexempel, dvs getCats
funktion.
Parallella databasanrop
En viktig sak att notera i ovanstående kod i rutthanterarfunktionen
const cats = await getCats();
const dogs = await getDogs();
const budgies = await getBudgies();
är att detta kommer att leda till sekventiella databasanrop som kanske eller kanske inte vad du vill.
Om dessa databasanrop inte är beroende av varandra kan du anropa de löftesbaserade omslagen parallellt med Promise.all()
metod.
Följande kodexempel visar hur du kan anropa dina löftesbaserade omslagsfunktioner parallellt med 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) {
...
}
});
Jag hoppas att detta är tillräckligt för att hjälpa dig att bli av med de kapslade databasanropen i din nuvarande kod och börja använda löften i din kod.