This content originally appeared on DEV Community and was authored by Domantas Jurkus
I was connecting a gRPC service with my node service and ran into an issue that i wanted to document for future sake.
The problem
I have a controller that looks like this:
export class MyController {
static getItem = async (_req: Request, res: Response): Promise<void> => {
const data = await myService.getItem();
console.log('controller: ', data);
res.status(200).json(data);
};
}
My service looks like this:
export class IstService {
// ... setup stuff
getItem = async () => {
await this.grpcClient.GetItem(
{ item_id: 'item-1234' },
(err: any, response: Record<string, unknown>) => {
if (err) {
console.error(err);
return;
}
console.log('service:', JSON.stringify(response));
return response;
}
);
};
}
When I call the controller, the log order is:
apps/server start:dev: [1] controller: undefined
apps/server start:dev: [1] service: {"id": "item-1234", "foo": "bar"}
Uh oh, that’s not what I want. While I have an await before myService.getItem(), the controller still finishes execution first before the gRPC call finishes.
The solution
The solution to this problem is to wrap the service gRPC call into a new Promise:
export class IstService {
// ... setup stuff
getItem = async () => {
return new Promise((resolve, reject) => {
this.grpcClient.GetItem(
{ item_id: 'item-1234' },
(err: any, response: Record<string, unknown>) => {
if (err) {
reject(err);
return;
}
console.log('service:', JSON.stringify(response));
resolve(response);
}
);
});
};
}
The main issue here is that this.grpcClient.GetItem does not use the async/await API – it uses the traditional callback pattern, where you essentially have to nest your code into the callback function.
JavaScript/TypeScript does not stop you from putting await on places where it does not make sense (would be nice is TypeScript had some automatic warning for pointless cases like these):
await console.log("just weird")
This content originally appeared on DEV Community and was authored by Domantas Jurkus