K
K
Konstantin2021-01-16 02:43:13
Angular
Konstantin, 2021-01-16 02:43:13

What could be the reasons for the code to run for a long time?

There is a method that is called every time upon receiving data from the server, which is looking for a record from the answer in the existing list of objects in several fields.

When the list is large enough, around 200 elements, the method noticeably loses performance.

What could be the reasons if you look at the code?

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

Answer the question

In order to leave comments, you need to log in

1 answer(s)
R
Ruslan Lopatin, 2021-01-16
@Junart1

Iterating over a list is slow (complexity O(n)). So it is quite logical to create indexes for large data sets. In your particular case, you can use Map (access complexity - O(1)).
It can be implemented in different ways. For example, to store a set of visitors (VisitorService.visitors$) not as a list, but as an object of a class that can efficiently search in this set.
Something like this:

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

}

Accordingly, VisitorService.visitors$the above has a type BehaviorSubject<VisitorCollection>and is filled with a call like
visitorService.visitors$.next(new VisitorCollection(visitorList))

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question