Одноэлементный атрибут Typescript Undefined

#javascript #node.js #typescript #singleton

#javascript #node.js #typescript #синглтон

Вопрос:

Я пытаюсь создать синглтон, который имеет одно соединение amqp, и когда вызывается метод CreateChannel, он должен возвращать новый канал из того же соединения:

 export interface IBroker {
  createChannel(): Promise<IChannel>;
}

export default class Broker implements IBroker {
  private static instance: Broker;

  private conn: IConnection | undefined;

  private constructor(public config: IRabbitMQConfig = new RabbitMQConfig()) {}

  /**
   * singleton
   */
  public static getInstance(): Broker {
    if (!this.instance) {
      this.instance = new Broker();
    }
    return this.instance;
  }

  /**
   * initiates configuration on infra service
   */
  async createChannel(): Promise<IChannel> {
    try {
      if (!this.conn) {
        this.conn = await this.config.init();
        await this.createExchanges();
        await this.createQueues();
        await this.createBinds();
        logger.info('Broker started successfully');
      }
      if (!this.conn) {
        throw new InternalError('Error starting broker. Missing connection!');
      }
      return await this.conn.createChannel();
    } catch (err) {
      logger.error('Error trying to start broker', err);
      throw new InternalError('Error trying to start broker', 500);
    }
  }

// code...
 

вызов config.init() возвращает соединение amqp.

когда я тестирую класс, как показано ниже, каждый раз, когда я вызываю CreateChannel, он создает новое соединение!

     const a = Broker.getInstance();
    const b = Broker.getInstance();
    console.log(a === b); // return true
    a.createChannel(); // create a new connection
    b.createChannel(); // creates another connection

 

this.conn класса Broker всегда не определен при вызове CreateChannel!

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

1. Как вы определяете, что он устанавливает новое соединение? Всегда ли первая if (!this.conn) ветвь вычисляется true как?

2. Я зарегистрировал this.conn, каждый раз, когда я вызываю метод CreateChannel брокера, он не определен! и успешно запущенный брокер сообщений тоже всегда отображается.

3. Разве вы не должны ожидать createChannel вызовов? К моменту вашего вызова b.createChannel , скорее async всего, операция по его инициализации еще не завершена.

4. конечно, это проблема.. Извините, что беспокою вас этой глупой ошибкой … большое вам спасибо!

Ответ №1:

Я думаю, проблема в том, что два синхронных вызова createChannel означают, что первый не инициализировал соединение к моменту вызова второго, что приводит к созданию 2 соединений.

Если вы хотите сделать свой createChannel «потокобезопасный» с точки зрения создания соединения, вы могли бы сделать что-то вроде этого (непроверенный):

 interface IConnection {
    connect: () => void
}

const initConnection = () : Promise<IConnection> => {
    return Promise.resolve({
        connect: () => {}
    });
};

class Broker {
    private connection : IConnection | undefined;
    private pendingConnection : Promise<IConnection> | undefined;

    async createChannel() : Promise<IConnection> {
        if (this.connection) {
            return this.connection;
        }

        if (this.pendingConnection) {
            return this.pendingConnection;
        }

        this.pendingConnection = initConnection();
        const conn = await this.pendingConnection;
        // Do other setup stuff
        this.connection = conn;
        this.pendingConnection = undefined;
        return conn;
    }
}