Какие могут быть причины долгой работы кода?

Есть такой метод, который вызывается каждый раз по получении данных от сервера, который ищет запись от ответа в существующем списке объектов по нескольким полям.

Когда список достаточно большой, около 200 элементов, метод заметно теряет производительность.

Какое могут быть причины, если взглянуть на код?

private listenScanerHandler(scanResponse: any): void {
    if (!scanResponse || scanResponse.errorDesc !== "SUCCESS") {
      this.messageService.showMessage(
        "",
        getMessage(GlobalModel.getCurrentLanguage(), "009"),
        "error"
      );
      return;
    }

    const foundVisitor = this.visitorsService.visitors$
      .getValue()
      .find((p: IVisitor) => {
        if (scanResponse && "qrcode" in scanResponse) {
          return (
            p.code && p.code.toLowerCase() === scanResponse.qrcode.toLowerCase()
          );
        } else {
          return (
            p.document_number &&
            scanResponse.document_number &&
            p.document_number.toLowerCase() ===
              scanResponse.document_number.toLowerCase()
          );
        }
      });

    if (foundVisitor) {
      this.visitorWasFound(foundVisitor);
    } else {
      this.visitorNotFound(scanResponse);
    }
  }
  • Вопрос задан
  • 135 просмотров
Решения вопроса 1
Перебор списка - это медленно (сложность O(n)). Так что вполне логично для больших наборов данных создавать индексы. В вашем конкретном случае можно использовать Map (сложность доступа - O(1)).

Реализовать можно по-разному. Например, хранить набор посетителей (VisitorService.visitors$) не как список, а как объект класса, умеющего эффективно в этом наборе искать.

Что-то вроде такого:
class VisitorCollection {

  private readonly _byDocumentNumber = new Map<string, IVisitor>();
  private readonly _byCode = new Map<string, IVisitor>();

  constructor(readonly list: readonly IVisitor[]) {
    // Fill the indices
    for (const visitor of list) {
      const { code, document_number } = visitor;
      if (code) {
        this._byCode.set(code.toLowerCase(), visitor);
      }
      if (document_number) {
        this._byDocumentNumber.set(document_number.toLowerCase(), visitor);
      }
    }
  }

  byDocumentNumber(documentNumber: string): IVisitor | undefined {
    return this._byDocumentNumber.get(documentNumber);
  }

  byCode(code: string): IVisitor | undefined {
    return this._byCode.get(code);
  }

}

class YourControllerClass {

  private listenScanerHandler(scanResponse: any): void {
    if (!scanResponse || scanResponse.errorDesc !== "SUCCESS") {
      this.messageService.showMessage(
        "",
        getMessage(GlobalModel.getCurrentLanguage(), "009"),
        "error"
      );
      return;
    }

    const visitors: VisitorCollection = this.visitorService.visitors$.getValue();
    const { qrcode, document_number } = scanResponse;
    let foundVisitor: IVisitor | undefined;

    if (qrcode) {
      foundVisitor = visitors.byCode(qrcode.toLowerCase());
    } else if (document_number) {
      foundVisitor = visitors.byDocumentNumber(document_number.toLowerCase());
    }

    if (foundVisitor) {
      this.visitorWasFound(foundVisitor);
    } else {
      this.visitorNotFound(scanResponse);
    }
  }

}


Соответственно, VisitorService.visitors$ выше имеет тип BehaviorSubject<VisitorCollection> и заполняется вызовом вроде
visitorService.visitors$.next(new VisitorCollection(visitorList))
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы