Как я могу продолжать запускать цикл for, если Observable не возвращает правильный ответ.

#angular #google-maps-api-3 #firebase #ionic2 #observable

# #angular #google-maps-api-3 #firebase #ionic2 #наблюдаемый

Вопрос:

Я использую API карт Google, чтобы позволить пользователю выполнять поиск по городу, а затем запрашиваю свою базу данных Firebase на основе addressstype. Ответ Google возвращает разные типы адресов (locality, add_level_1, add_level_2, …), и я хочу иметь возможность выполнять разные запросы, если я не получаю результата.

Как должен работать мой проект: я получаю объект API Google, затем на основе этой информации я ищу POI, сначала на основе «locality», если это не возвращает результат (в firebase не найдено объектов) Я выполняю тот же запрос, но на основе ‘adm_level_2’ и так далее.

Что у меня есть на данный момент: я могу получить ответ API Google, а затем выполнить запрос, чтобы найти POI на основе «locality», и показать этот ответ в моем приложении. Но я не могу понять, как выполнить второй (и третий) запрос, если первый запрос не возвращает результат.

Мой код до сих пор:

  var componentForm = {
        street_number: 'short_name',
        route: 'long_name',
        locality: 'long_name',
        administrative_area_level_1: 'short_name',
        administrative_area_level_2: 'long_name',
        country: 'long_name',
        postal_code: 'short_name'
      };

  for (var i = 0; i < place.address_components.length; i  ) {
    this.addressType = place.address_components[i].types[0];
    if (componentForm[this.addressType]) {
      if (this.addressType == "locality") {
        this.locality = place.address_components[i][componentForm[this.addressType]];
         let rsltBusiness = [];
         self._dataService.getCompaniesForLocationObs(this.addressType,this.locality)
          .map(i=>{return i})
          .subscribe(i => self.staticData =i
          );
      }
      if (this.addressType == "administrative_area_level_2") {
        console.log("adm_level_2 ");
        this.adm_level2 = place.address_components[i][componentForm[this.addressType]];
      } if (this.addressType == "administrative_area_level_1") {
        this.adm_level1 = place.address_components[i][componentForm[this.addressType]];
      }
    }
  }
 

Итак, первая часть, которая работает, находится в ‘ if (this.AddressType == «locality»)’, но если это не возвращает результат, я должен иметь возможность выполнить тот же запрос, но затем из ‘if (this.AddressType == «administrative_area_level_2») {‘

Возможно ли это? И если да, как мне с этим справиться? Или я пытаюсь сделать что-то, что противоречит правильному использованию Observables и Angular2 / Firebase?

У меня нет большого опыта работы с Angular2, поэтому я был бы признателен за любую помощь.

Ответ №1:

Не уверен, что это сработает из коробки, поскольку я не могу протестировать код, но я попытаюсь объяснить принцип, вы его реализуете:

 // create a list of types you want to check against from API response

  let addressTypes = [];
  let addressLocality = {};
  for (var i = 0; i < place.address_components.length; i  ) {
    let type = place.address_components[i].types[0]
    addressTypes.push( type );
    addressLocality[ type ] = place.address_components[i][componentForm[type]]
  }

// Search database for each 'addressType' you found.
   Observable.from(addressTypes)
     .mergeMap(type => self._dataService
       .getCompaniesForLocationObs(type, addressLocality[type]))

// Assuming 'getCompaniesForLocationObs()' returns false if it doesn't find anything
      .filter(Boolean)

// If something is found stop 
       .take(1)

// Execute!
       .subscribe(i => self.staticData = i)
 

Помните, что observable оценивает всю цепочку операторов, которые вы настроили для каждого исходного элемента, прежде чем оценивать следующий. Итак, вам просто нужно создать список вещей, которые вы хотите запросить из ответа API (мой for-цикл, вероятно, не будет работать), и пусть observable сделает это (;

И не забывайте об импорте:

 import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/mergeMap';
import 'rxjs/add/operator/take'; 
import 'rxjs/add/operator/filter'; 
 

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

1. Спасибо, это именно то, что я искал, но, к сожалению, я все еще не могу показать правильный ответ. Я думаю, это может быть как-то связано с тем, как я получаю свой ответ Firebase?

2. промозглый, нажал enter, чтобы скоро. 🙂 ниже приведен мой запрос Firebase и то, как я возвращаю данные, было бы весьма признателен, если бы вы могли взглянуть и посмотреть, может быть, я делаю что-то не так? getCompaniesForLocationObs(index, location){ var businessList; return businessList = this.af.database.list(‘/business/’ , { query: { orderByChild: index, equalTo: location } }) }

3. Вы не получаете данные из FB или наблюдаемый не работает? Ваша функция возвращает пустой массив (af.db.list() возвращает пустой массив, если ничего не найдено), поэтому .filter(Boolean) в моем коде это не сработает. Если это проблема, замените его на .filter(res => res.length > 0) или аналогичный. Не вижу здесь ничего другого, что могло бы вызвать проблемы…

4. Да, именно в этом и заключалась проблема. Я не смог найти никакой информации о том, что af.db.list() вернул пустой массив. Спасибо.