Reputation: 170
I'm using Next.js, Auth.js and mongoose,
my problem is I wanted to wrap all my controllers with a wrapper/helper function called withDBConnection
to save me time not establishing a connection with the db each time, it takes the controller and returns it after connecting:
type Controller <Args extends any[]> = (...args: Args) => any;
export const withDBConnection = <Args extends any[]> (Controller:Controller<Args>):(...args:Args) => Promise<any> => {
return async (...args: Args) => {
try {
await dbStartConnection();
Controller(...args);
} catch (error) {
console.log("inside withDBConnection catch block");
console.log((error as AppError).message);
}
};}
an example of using the helper function:
export const getUser = withDBConnection( async(email: string) => {
const user = await Auth.find({discordEmail: email});
console.log("getUser", user);
return user;
});
but the controller doesn't return the value, which is user
, I can't use it in the Auth.js signIn()
callback:
const isExist = await getUser(user.email);
isExist
is always undefined
so the app goes to createNewUser
controller:
if(!isExist) await createNewUser(user);
I tried to change the return type from any
to mongoose type Document
in both type Controller
and withDBConnection
but that made the ts complain about the email: string
Upvotes: 1
Views: 42
Reputation: 56
The main issue was that Controller(...args); is called without returning its result, causing the wrapped function to return undefined. The following code properly awaits and returns the result from Controller
type Controller<Args extends any[]> = (...args: Args) => Promise<any>;
export const withDBConnection = <Args extends any[]>(
Controller: Controller<Args>
): ((...args: Args) => Promise<any>) => {
return async (...args: Args) => {
try {
await dbStartConnection();
return await Controller(...args);
} catch (error) {
console.log("inside withDBConnection catch block");
console.log((error as AppError).message);
throw error;
}
};
};
Edit: Here Controller(...args)
is executed, and since it's an async function, it returns a Promise immediately.
Immediately , the execution of withDBConnection
continues, and the function returns a Promise that resolves to undefined, because there's no explicit return statement.
But by return await Controller(...args)
ensures that:
The execution of withDBConnection waits for the async operation in Controller to complete.
If you are interested in learning concurrency you definitely need to check out
Upvotes: 3