Как получить точный последний ответ на HTML, используя наблюдаемый в angular12

Я использую Angular12, и здесь я использую автозаполнение в угловом материале, здесь проблема в том, что я могу получить результат на основе обращения к API, но в html я всегда получаю последний ответ-1.

Ц:

  private getAutoPopulateData(serchVal: any): Observable<string[]> {
    let data: any = [];
    let results: any = [];
    if (serchVal && serchVal.length > 0) {
      this.searchService.searchOpenSearchData(serchVal).subscribe((searchData: AutoPopulate) => {
        results = searchData.hits;
        if (results.hits.length > 0) {
          results.hits.forEach(h=>{
            let item=h._source;
             let addressProps=Object.keys(item).filter(p=> p.startsWith('AddressLine') && item[p].length >0);
             addressProps.forEach(ap=>{
                let addresses=item[ap].map((ai,idx)=>{
                 let address= `${ai} ${item.City[idx]} ${item.State} ${item.Zip[idx]}`;
                 return {name:item.ProfileName,address}
                });
               data= data.concat(addresses);
               this.seeResultsData = data.length;
             })
            });
        }
        this.resultData = of(data);
        this.isLoading = false;
      });
    }
    else {
      this.isLoading = false
    }
    if (this.resultData) {
      return this.resultData;
    } else 
    return null
  }

  private autoCompleteFormInit() {
    this.stateCtrl.valueChanges.pipe(
      debounceTime(500),
      tap((() => this.isLoading = true)),
      map(value => (this.getAutoPopulateData(value))
        .pipe(finalize(() => this.isLoading = false)))
    ).subscribe(value => {
    this.filteredOptions = value
    });
  }

public resultData: Observable<any> = of([]);
filteredOptions: Observable<any> = of([]);
searchOpenSearchData(searchValue:any): Observable<AutoPopulate> {
     let url =  URLConstants.openSearchUrl + searchValue;
     return this.http.get<AutoPopulate>(url);
   }

HTML:

 <input matInput aria-label = "State" placeholder = "Enter a Name" [matAutocomplete] = "auto" class = "paddingleft-5 text-medium" (ngModelChange) = "updatedVal($event)" type = "text" [formControl] = "stateCtrl" *ngIf = "form.value.tradingPartnerValue && dropdownSelection == 'tradingPartnerName'"/>
        <mat-autocomplete #auto = "matAutocomplete" (optionSelected) = "onOptionSelected($event.option)">
          <div *ngIf = "showAutocomplete" class = "{{seeResultsData >3 ? 'set-height' : ''}}">
            <mat-option *ngIf = "isLoading" class = "is-loading content-center">
              <mat-spinner diameter = "50" class = "show-center"></mat-spinner>
            </mat-option>
            <ng-container *ngIf = "!isLoading">
            <mat-option class = "option-custom text-medium" *ngFor = "let state of filteredOptions | async"
              [value] = "state" [ngClass] = "{'hide-autocomplete': !showAutocomplete}">
                <span [innerHTML] = "state.name | highlight : stateCtrl.value"></span>
                <span [innerHTML] = "state.address | highlight : stateCtrl.value"></span>
            </mat-option>
            </ng-container>
          </div>
</mat-autocomplete>

Json-ответ:

{
  "took": 178,
  "timed_out": false,
  "_shards": {
    "total": 0,
    "successful": 0,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": {
      "value": 10000,
      "relation": "gte"
    },
    "max_score": 12.9226,
    "hits": [
      {
        "_index": "pulse",
        "_id": "17320",
        "_score": 12.9226,
        "_source": {
          "ProfileName": "Pharmarx Pharmaceutical Inc",
          "State": "CA",
          "BusinessModel": "Dispenser",
          "LicenseInfo": [
            {
              "LicenseType": "Resident Licensed Sterile Compounding",
              "LicenseNumber": "99658",
              "AddressLine1": "21441 Osborne St Ste C & D",
              "AddressLine2": "",
              "AddressLine3": "",
              "AddressLine4": "",
              "Zip": "91304",
              "City": "Canoga Park"
            },
            {
              "LicenseType": "Retail Pharmacy",
              "LicenseNumber": "50511",
              "AddressLine1": "21441 Osborne St Ste C & D",
              "AddressLine2": "",
              "AddressLine3": "",
              "AddressLine4": "",
              "Zip": "91304",
              "City": "Canoga Park"
            }
          ]
        }
      },
      {
        "_index": "pulse",
        "_id": "7723",
        "_score": 10.891928,
        "_source": {
          "ProfileName": "ENCINO PHARMACY_AKA MDR PHARMACEUTICAL CARE",
          "State": "MI",
          "BusinessModel": "Dispenser",
          "LicenseInfo": [
            {
              "LicenseType": "PHARMACY",
              "LicenseNumber": "5301010993",
              "AddressLine1": "17071 VENTURA BLVD STE 100",
              "AddressLine2": "",
              "AddressLine3": "",
              "AddressLine4": "",
              "Zip": "91316",
              "City": "ENCINO"
            }
          ]
        }
      },
      {
        "_index": "pulse",
        "_id": "7724",
        "_score": 9.796367,
        "_source": {
          "ProfileName": "Encino Pharmacy_aka Mdr Pharmaceutical Care",
          "State": "CA",
          "BusinessModel": "Dispenser",
          "LicenseInfo": [
            {
              "LicenseType": "Retail Pharmacy",
              "LicenseNumber": "34818",
              "AddressLine1": "17059-17071 VENTURA BLVD.",
              "AddressLine2": "STE. 100",
              "AddressLine3": "",
              "AddressLine4": "",
              "Zip": "91316",
              "City": "ENCINO"
            }
          ]
        }
      },
      {
        "_index": "pulse",
        "_id": "192",
        "_score": 9.656487,
        "_source": {
          "ProfileName": "Abdin Pharmacies Pharma LLC",
          "State": "FL",
          "BusinessModel": "Dispenser",
          "LicenseInfo": [
            {
              "LicenseType": "Pharmacy",
              "LicenseNumber": "036936",
              "AddressLine1": "1873 SECOND AVE. NEW",
              "AddressLine2": "",
              "AddressLine3": "",
              "AddressLine4": "",
              "Zip": "10029",
              "City": "YORK"
            },
            {
              "LicenseType": "Pharmacy",
              "LicenseNumber": "033404",
              "AddressLine1": "1401 BRONX RIVER AVE.",
              "AddressLine2": "",
              "AddressLine3": "",
              "AddressLine4": "",
              "Zip": "10472",
              "City": "BRONX"
            },
            {
              "LicenseType": "Pharmacy",
              "LicenseNumber": "PH33043",
              "AddressLine1": "32866 US Hwy 19N",
              "AddressLine2": "",
              "AddressLine3": "",
              "AddressLine4": "",
              "Zip": "34684",
              "City": "PALM HARBOR"
            }
          ]
        }
      },
      {
        "_index": "pulse",
        "_id": "17304",
        "_score": 9.186218,
        "_source": {
          "ProfileName": "PHARMALABS, LLC PharmaLabs",
          "State": "FL",
          "BusinessModel": "Dispenser",
          "LicenseInfo": [
            {
              "LicenseType": "Pharmacy",
              "LicenseNumber": "PH26495",
              "AddressLine1": "10901 ROOSEVELT BOULEVARD NORTH SUITE 1200",
              "AddressLine2": "",
              "AddressLine3": "",
              "AddressLine4": "",
              "Zip": "33716",
              "City": "Saint Petersburg"
            }
          ]
        }
      }
    ]
  }
}

в пользовательском интерфейсе мне нужно отобразить, Имя профиля как имя в пользовательском интерфейсе, а также несколько адресов, представленных под одним и тем же именем профиля, например, один образец, который я взял из json, поэтому из этого массива объектов должен содержать,

[{name:'Pharmarx Pharmaceutical Inc', address:'21441 Osborne St Ste C & D,Canoga Park CA 9104'},
{name:'Pharmarx Pharmaceutical Inc', address:'21442 Osborne St Ste C & D(Address2/Address3/Address4)what ever is present must show, Canoga Park CA 9104'}]

так что это похоже на одно имя профиля, у нас есть несколько адресов местоположения

 "_source": {
      "ProfileName": "Pharmarx Pharmaceutical Inc",
      "State": "CA",
      "BusinessModel": "Dispenser",
      "LicenseInfo": [
        {
          "LicenseType": "Resident Licensed Sterile Compounding",
          "LicenseNumber": "99658",
          "AddressLine1": "21441 Osborne St Ste C & D",
          "AddressLine2": "",
          "AddressLine3": "",
          "AddressLine4": "",
          "Zip": "91304",
          "City": "Canoga Park"
        },
        {
          "LicenseType": "Retail Pharmacy",
          "LicenseNumber": "50511",
          "AddressLine1": "21441 Osborne St Ste C & D",
          "AddressLine2": "",
          "AddressLine3": "",
          "AddressLine4": "",
          "Zip": "91304",
          "City": "Canoga Park"
        }
      ]
    }
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Angular и React для вашего проекта веб-разработки?
Angular и React для вашего проекта веб-разработки?
Когда дело доходит до веб-разработки, выбор правильного front-end фреймворка имеет решающее значение. Angular и React - два самых популярных...
Эпизод 23/17: Twitter Space о будущем Angular, Tiny Conf
Эпизод 23/17: Twitter Space о будущем Angular, Tiny Conf
Мы провели Twitter Space, обсудив несколько проблем, связанных с последними дополнениями в Angular. Также прошла Angular Tiny Conf с 25 докладами.
Угловой продивер
Угловой продивер
Оригинал этой статьи на турецком языке. ChatGPT используется только для перевода на английский язык.
Мое недавнее углубление в Angular
Мое недавнее углубление в Angular
Недавно я провел некоторое время, изучая фреймворк Angular, и я хотел поделиться своим опытом со всеми вами. Как человек, который любит глубоко...
Освоение Observables и Subjects в Rxjs:
Освоение Observables и Subjects в Rxjs:
Давайте начнем с основ и постепенно перейдем к более продвинутым концепциям в RxJS в Angular
0
0
106
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

У вас есть некоторые проблемы в вашем коде, но основная причина, по которой вы получаете предыдущий результат, заключается в том, что вы делаете:

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

Если this.resultData заполнен данными из предыдущего запроса, он вернется непосредственно перед тем, как наблюдаемый (this.searchService.searchOpenSearchData(serchVal)) испустит и установит новое значение для this.resultData.

Вы должны установить this.resultData результат наблюдаемого из запроса API и дождаться результата, а не возвращать его, как вы сделали в своем коде.

Что-то вроде:

private getAutoPopulateData(serchVal: any): Observable<string[]> {
  let data: any = [];
  let results: any = [];
  if (serchVal && serchVal.length > 0) {
    this.isLoading = true;
    this.resultData = this.searchService.searchOpenSearchData(serchVal).pipe(
      map((searchData: AutoPopulate) => {
        results = searchData.hits;
        if (results.hits.length > 0) {
          results.hits.forEach(h => {
            let item=h._source;
            let addressProps=Object.keys(item).filter(
              p => p.startsWith('AddressLine') && item[p].length > 0
            );
            addressProps.forEach(ap => {
              let addresses=item[ap].map((ai,idx)=>{
              let address= `${ai} ${item.City[idx]} ${item.State} ${item.Zip[idx]}`;
              return {name:item.ProfileName, address}
            });
            data = data.concat(addresses);
            this.seeResultsData = data.length;
          });
          return data;
        }
        return null;
      }),
      finalize(() => this.isLoading = false);
    );
  } else {
    this.resultData = of(null);
  }
  return this.resultData;
}

Я попытался вернуть null там, где это необходимо, но проверьте, соответствуют ли эти места вашим потребностям (возможно, вместо этого вы хотите вернуть пустой массив). Я использовал pipe, map и finalize из rxjs, которые нужно импортировать. Я переместил ваш isLoading = false в завершение, чтобы он также «переставал загружаться» при ответах на ошибки.

Если еще вопросы, оставьте комментарий.

ОБНОВЛЯТЬ

После того, как вы добавили дополнительный код к своему вопросу в «редактировании», я должен обновить свой ответ:

С изменениями, о которых я упоминал выше, ваш метод autoCompleteFormInit должен измениться следующим образом:

private this.subscription: Subscription;

private autoCompleteFormInit() {
  this.subscription = this.stateCtrl.valueChanges.pipe(
    debounceTime(500),
    switchMap(value => this.getAutoPopulateData(value))
  ).subscribe(value => this.filteredOptions = value);
}

// To prevent memory leaks, store subscription and unsubscribe on destroy
public ngOnDestroy(): void {
  if (this.subscription) this.subscription.unsubscribe();
}

Я также изменил логику относительно isLoading, лучше, чтобы он вызывался только в методе, который фактически отправляет запрос.

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

с приведенным выше кодом он не попадает в API, и я не могу увидеть ошибку также в консоли

Bhrungarajni 12.04.2023 15:28

@Bhrungarajni Вам нужно подписаться на наблюдаемое, где вы вызываете getAutoPopulateData вне этого кода. Если вы нигде не подпишитесь, он не будет выполнять наблюдаемое.

Wilt 12.04.2023 17:19

да, я подписался на метод автозаполнения

Bhrungarajni 12.04.2023 17:29

@Bhrungarajni Этот код с методом автозаполнения был добавлен к вопросу после того, как я ответил. Когда вы задаете вопрос, вы должны убедиться, что добавлены все соответствующие части кода. Я посмотрю позже, смогу ли я обновить свой ответ...

Wilt 20.04.2023 11:40

Пожалуйста, Уилт, сегодня я добавил данные json на основе ответа Дэниела.

Bhrungarajni 20.04.2023 12:19

спасибо за ответ, Уилт, так что мне нужно добавить оба метода из вашего кода, верно?

Bhrungarajni 20.04.2023 12:45

API работает, но не может видеть данные в html, я имею в виду, что значение в раскрывающемся списке не отображается

Bhrungarajni 20.04.2023 12:48

Давайте продолжим обсуждение в чате.

Bhrungarajni 20.04.2023 12:49

привет @Wilt, не могли бы вы проверить это, stackoverflow.com/questions/76217665/…

Bhrungarajni 11.05.2023 05:35

Другие вопросы по теме