I'm writing some code that grabs some result asynchronously and stores it until later, when another function needs it, sort of like eager loading it. (In my specific case I'm grabbing a secret from AWS Secrets manager, but whatever.) My code looks like this:
const secretPromise = new Promise((resolve, reject) => {
try {
const credentialsJSON = await new AWSController().getSecret("my-credentials");
resolve(JSON.parse(credentialsJSON));
} catch (e) {
reject(new Error(`Error getting credentials: ${e.message}`));
}
});
// in an expressJS route handler:
router.get("/groups", async (request, response) => {
try {
const credentials = await secretPromise;
const result = await doSomething(credentials);
response.send(JSON.stringify(result));
} catch (error){
response.status(503).send(`Error: ${error.message)`);
}
});
What I didn't realize was that if there's no handler for this promise, it will throw an error and crash my nodeJS code immediately. Is there a way to store the result or error and handle it later? I don't want my server to crash just because one API function won't work.
CodePudding user response:
You create the secretPromise
early, outside of the route handler. It may therefore be rejected before the route handler is called, when there is no try-catch block that would catch that rejection.
A rejected secretPromise
causes every subsequent GET /groups
request to fail, you could handle this without a rejection:
const secretPromise = new Promise((resolve, reject) => {
try {
const credentialsJSON = await new AWSController().getSecret("my-credentials");
resolve(JSON.parse(credentialsJSON));
} catch (e) {
resolve({error: new Error(`Error getting credentials: ${e.message}`)});
}
});
// in an expressJS route handler:
router.get("/groups", async (request, response) => {
try {
const credentials = await secretPromise;
if (secretPromise.error) throw secretPromise.error;
const result = await doSomething(credentials);
response.send(JSON.stringify(result));
} catch (error){
response.status(503).send(`Error: ${error.message)`);
}
});
CodePudding user response:
The await inside secretPromise is not within an async function therefore the code isn't valid. Also there's no need to wrap it in a Promise.
To eagerly fetch the credentials before the API is called, I would simply write it like this:
let credentials;
try {
const credentialsJSON = await new AWSController().getSecret("my-credentials");
credentials = JSON.parse(credentialsJSON);
} catch (e) {
credentials = new Error(`Error getting credentials: ${e.message}`);
}
};
// in an expressJS route handler:
router.get("/groups", async (request, response) => {
try {
if (credentials instanceof Error) {
throw credentials;
}
const result = await doSomething(credentials);
response.send(JSON.stringify(result));
} catch (error){
response.status(503).send(`Error: ${error.message)`);
}
});