Search code examples
javascripttypescriptgrpc-node

Async/Await not working as expected with gRPC method


this is the code to initialize a gRPC server I am using:

export const initServer = async (finalPort: number): Promise<string> => {
  let initStatus = 'initial';
  gRPCserver.addService(webcomponentHandler.service, webcomponentHandler.handler);

  // define the host/port for server
  await gRPCserver.bindAsync(
    `localhost:${finalPort}`,
    grpc.ServerCredentials.createInsecure(),
    (err: Error | null, port1: number) => {
      if (err != null) {
        console.error(err);
        log.info('Biding Error');
        initStatus = 'Binding Error';
      }
      // start the gRPC server
      gRPCserver.start();
      log.info(`startServer::gRPC server started, on port: ${port1}`);
      initStatus = 'OK';
    },
  );
  return initStatus;
};

I am trying to return that initStatus to this function:

type StartServerType = () => Promise<string | undefined>;
export const startServer: StartServerType = async (): Promise<string | undefined> => {
  try {
    let initStatusResponse;
    // Get port
    const finalPort = port();
    await server.initServer(finalPort).then((res) => {
      initStatusResponse = res;
      log.info('INIT STATUS RESPONSE: ', initStatusResponse);
    });
  } catch (e: unknown) {
    if (typeof e === 'string') {
      return e.toUpperCase(); // works, `e` narrowed to string
    }
    if (e instanceof Error) {
      return e.message; // works, `e` narrowed to Error
    }
  }
  return 'started';
};

But I always received 'initial' as initStatusResponse. I know there is an async issue there, but I can not see where.

Thanks in advance.


Solution

  • You will need to check the documentation for gRPCserver.bindAsync but it would seem that this method does not return a promise object. The likelihood of this is increased because you are passing a callback function as an argument. Promise objects remove the need for callback functions (Often referred to as "callback hell"). Here is an article that explains the differences between the different ways to do asynchronous actions in Javascript/Typescript.

    Using async/await is a good approach. In order to use it if gRPCserver.bindAsync doesn't return a promise we can "wrap" it in a promise. This can be done easily with the node.js util promisify (Documentation) or manually with new Promise. This article explains both ways well.