Angular 2, выполняющий наблюдаемые объекты последовательно

#angular #observable

#angular #наблюдаемый

Вопрос:

У меня есть следующий метод:

  getProject(name) {
  this.ProjectName = name;
  //Friendly URL to ID --> FIRST OBSERVABLE
   this.af.database.object('/friendly_urls/'   name).take(1).share().map((data) => {
    //ID to data --> SECOND OBSERVABLE
     this.af.database.object('/Project/'   data.$value).take(1).map((ProjectData) => {
       console.log("Received Project data");
      this.ProjectData = ProjectData;
    });
  },
  error =>  {
    console.log(error);
    /* TODO: Permission blocked page */
    this.router.navigate(['']);
  });
}
}
  

У меня есть 2 наблюдаемых объекта: первый наблюдаемый объект, который выполняется первым, и второй, который выполняется сразу после него.

Я пытался понять, как использовать это в моем случае, и не смог этого понять.

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

Ответ №1:

Используйте switchMap , чтобы взять значение из первого наблюдаемого и использовать его как начальное значение для 2-го наблюдаемого. Сначала вы настраиваете (составляете) поток:

 projectData$ = this.af.database.object('/friendly_urls/' name).share().switchMap(
    data => this.af.database.object('/Project/' data.$value)
).take(1);
  

Затем, когда вы хотите извлечь данные, просто subscribe :

 projectData$.subscribe(
    projectData => this.ProjectData = projectData,
    error => console.log(error);
)
  

Подробнее о switchMap

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

1. Привет, спасибо! Но если я подпишусь на projectData$ , ProjectData переменная будет наблюдаемой this.af.database.object('/Project/' data.$value) , а не фактической информацией, которая мне нужна (которая является подпиской на это наблюдаемое)

2. Это приводит к тому, что мне нужно сделать 2 подписки, как и раньше, одну за другой. ProjectData.subscribe((data) => { this.RealProjectData = data } );

3. @Elikos Я знаю, что database.object возвращает наблюдаемое. Вот почему я использую switchMap вместо map . Вы уже пробовали мое решение, и оно не удалось, или вы делаете прогноз о том, что произойдет?

4. Прошу прощения! Использовал .map все долгое время. Это работает потрясающе! Спасибо вам.

5. Можете ли вы опубликовать пример, как сделать то же самое с 3 наблюдаемыми объектами, зависящими друг от друга?

Ответ №2:

Вы должны использовать оператор static concat , который подписывается на первый наблюдаемый объект, а после завершения — на второй.

 let obs1 = this.af.database.object('/friendly_urls/'   name).map(data => data.$value);
let obs2 = this.af.database.object('/Project/'   data.$value).map(project => this.ProjectData = project);

let concatenatedObservables = Observable.concat(obs1, obs2);

concatenatedObservables.subscribe();
  

Подробнее об этом здесьhttp://reactivex.io/rxjs/class/es6/Observable.js ~Observable.html#экземпляр-метод-объединение

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

1. Это не сработает, поскольку автор использует data возвращенные из obs 1 данные в качестве входных данных для obs 2. concat запускает их в независимых контекстах.