Асинхронность/Ожидание не работает должным образом с методом gRPC

#javascript #typescript #grpc-node

Вопрос:

это код для инициализации сервера gRPC, который я использую:

 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;
};
 

Я пытаюсь вернуть этот статус в эту функцию:

 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';
};
 

Но я всегда получал «начальный» в качестве ответа на запрос. Я знаю, что там есть проблема с асинхронностью, но я не вижу, где именно.

Заранее спасибо.

Комментарии:

1. по моему опыту, функция, которая выполняет обратный вызов, редко возвращает обещание, поэтому await gRPCserver.bindAsync..... вряд ли будет работать так, как вы хотите

2. Я согласен, bindAsync принимает функцию обратного вызова, поэтому она не возвращает обещание, так await что это бессмысленно. Следующая строка кода ( return initStatus; ) будет выполнена немедленно, до initStatus того, как будет задана.

3.чтобы быть ясным async await , работает с обещаниями, а не с чем-то неопределенно асинхронным

4. Кроме того, вы смешиваете await и .then() синтаксис вместе. Вы не можете использовать и то, и другое одновременно, .then() полностью избавьтесь от этого.

5. @JeremyThille — неправда, вы можете смешивать два — это просто не очень хорошая практика :p

Ответ №1:

Вам нужно будет проверить документацию gRPCserver.bindAsync , но, похоже, этот метод не возвращает объект promise. Вероятность этого возрастает, поскольку вы передаете функцию обратного вызова в качестве аргумента. Объекты Promise устраняют необходимость в функциях обратного вызова (часто называемых «адом обратного вызова»). Вот статья, в которой объясняются различия между различными способами выполнения асинхронных действий в Javascript/Typescript.

Использование async/await-хороший подход. Чтобы использовать его, если gRPCserver.bindAsync он не вернет обещание, мы можем «завернуть» его в обещание. Это можно легко сделать с помощью node.js util promisify (Документация) или вручную с new Promise помощью . В этой статье хорошо объясняются оба способа.