0

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.

Datenshi
  • 59
  • 1
  • 9
  • 2
    in my experience, a function that takes a callback rarely returns a Promise - so `await gRPCserver.bindAsync.....` is unlikely to works as you want – Bravo Aug 02 '21 at 08:27
  • I agree, `bindAsync` takes a callback function, therefore it doesn't return a Promise, so `await`ing it is pointless. The next line of code (`return initStatus;`) will execute immediately, before `initStatus` is set. – Jeremy Thille Aug 02 '21 at 08:30
  • 1
    to be clear `async` `await` works with Promises, not anything vaguely asynchronous – Bravo Aug 02 '21 at 08:30
  • Also, you are mixing `await` and the `.then()` syntax together. You can't use both at the same time, get rid of `.then()` entirely. – Jeremy Thille Aug 02 '21 at 08:32
  • @JeremyThille - not true, you can mix the two - it's just not good practice :p – Bravo Aug 02 '21 at 08:36
  • Okay you _can_, it doesn't crash or anything, but awaiting something that doesn't return a Promise is pointless. Let's say you _shouldn't_. – Jeremy Thille Aug 02 '21 at 08:43
  • I never said anything about you can await something that doesn't return a promsie ... I was referring to your "mixing of await and .then" remark - because of course you can do that -since `.then` returns a Promise - Put it this way, I have one piece of code that does mix the two - because trying to use just `await` makes the code messy, and just using `.then` makes a bit of callback hell – Bravo Aug 02 '21 at 08:47

1 Answers1

2

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.

user9540018
  • 507
  • 3
  • 11