2017-02-15 1 views
0

Я работаю с наблюдаемыми, и я изо всех сил пытаюсь понять, как работать с ними в циклах.Нужна помощь в понимании прикованных наблюдаемых

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

Вот пример кода, о котором я думаю (обратите внимание, что это угловой 2).

public load(): void { 
    this.loadParts(this.parts).subscribe(() => { 
    // This code should wait to run until all of these observables are complete. However for some reason I get here before I get to the code inside the httpService.get observable inside the loadMaterial method below. 
    } 
} 

private loadParts(parts: Part[]): Observable<any> { 
    Observable.create((observer: any) => { 
    for(part of parts) { 
     this.applyMaterial(part.material).subscribe(); 
    } 
    // This observer should be completed when the for loop is done and all materials have been applied. 
    observer.next(); 
    observer.complete(); 
    }); 
} 

private applyMaterial(material: Material[]): Observable<any> { 
    this.loadMaterial(material.id).subscribe(() => { 
    // We need to request the material from the server and wait for the response before applying it here. 
    } 
} 

private loadMaterial(materialId: String): Observable<any> { 
    this.httpService.get(API.LoadMaterialsURL + '/' + materialId).subscribe((response: any) => { 
    // Update the material service to include the material data returned by the response. 
    }); 
} 

ответ

0

Я вижу две ошибки в коде:

  • Вы subscribe слишком часто. Вы должны придерживаться трансформации/привязки оригинала, наблюдаемого как можно дольше, и только подписываться в конце, из кода, потребляющего наблюдаемое (т. Е. Кода, который должен использовать значения, которые наблюдаемые испускают).
  • Все ваши методы не имеют инструкции return, что означает, что NONE из них возвращает наблюдаемый.

Вот грубый набросок, показывающий, как вы можете сетевые операторы, пока вы не получите данные, которые вы хотите:

const partIds = [1, 2, 3, 4]; 

const materialsObs = Observable.from(partIds) 

    // load the part for a given part id 
    .mergeMap(partId => this.http.get(`http://api.com/part/${partId}`)) 

    // extract the material id from the loaded part 
    .map(loadedPart => loadedPart.material.id) 

    // load the material for a given material id 
    .mergeMap(materialId => this.http.get(`http://api.com/material/${materialId}`)); 

Ключ заключается в использовании mergeMap() оператору каждый раз, когда вам нужно передать значение другой наблюдаемой ,

Тогда вы только подписаться РАЗ, когда вы на самом деле нужно использовать конечные значения:

materialsObs.subscribe(material => console.log(material)); 
Смежные вопросы