2017-05-02 65 views
1

的可觀表達我有,有一個方法,它本質上是一種服務:Angular2/rxjs:訂閱不開火mergeMaps&forkJoins

this.backend.getJSON(`${name}/book`).mergeMap(
    book => Observable.forkJoin(book.parts.map((partName: string) => 
    this.backend.getJSON(`${name}/${partName}/part`).mergeMap(
     part => Observable.forkJoin(part.sections.map((sectionName: string) => 
     this.backend.getJSON(`${name}/${partName}/${sectionName}/section`).mergeMap(
      section => Observable.forkJoin(section.chapters.map((chapterName: string) => 
      this.backend.getJSON(`${name}/${partName}/${sectionName}/${chapterName}/chapter`).map(chapter => { 
       this.transform(chapter.content, `${name}/${partName}/${sectionName}/${chapterName}`); 
       return chapter; 
      }))), 
      this.assignAndReturn('chapters'))), 
     this.assignAndReturn('sections'))))), 
    this.assignAndReturn('parts')); 

(我內聯 - 稍微簡化 - 一些所謂的方法,這就是爲什麼它是這樣一個龐大的表達,因此在getJSON ARGS重複)

assignAndReturn就是:

private assignAndReturn<T1, T2>(name: string) { 
    return (a: T1, b: T2) => { 
    a[name] = b; 
    return a; 
    }; 
} 

.subscribe(...)對此似乎不起作用。它似乎只能在表達樹中下移,而不是「成爲」獲得章節的途徑。

我真的不知道發生了什麼事。這幾乎就像我需要訂閱'內部'部分,但外部訂閱不會觸發...

回答

0

你可以嘗試一個這樣的模式,利用flatMap。一旦前一個事件結束,flatMap將繼續由它的回調返回Observable。它有助於提高可讀性,並使您能夠沿途監視您的流。

import { Observable } from 'rxjs'; 

class Demo { 
    backend = { 
     // Simulated request 
     getJSON: (str, demoValue) => Observable.of(demoValue).delay(new Date(Date.now() + 1000)) 
    } 

    getBook(name) { 
     this.backend 
      // Get the book 
      .getJSON(`${name}/book`, name) 
      // Get the parts 
      .flatMap(book => { 
       // Observable.from() will create an observable event 
       // for each item in the array 
       return this.backend 
        .getJSON(`[Next URL]`, [`${book}/part1`, `${book}/part2`]) 
        .flatMap(parts => Observable.from(parts)); 
      }) 
      // Get the sections 
      .flatMap(part => { 
       return this.backend 
        .getJSON(`[Next URL]`, [`${part}/section1`, `${part}/section`]) 
        .flatMap(sections => Observable.from(sections)); 
      }) 
      // Get the chapters 
      .flatMap(section => { 
       return this.backend 
        .getJSON(`[Next URL]`, [`${section}/chapter1`, `${section}/chapter2`]) 
        .flatMap(chapters => Observable.from(chapters)); 
      }) 
      // etc. 
      .subscribe(console.log) 
    } 
} 

let t = new Demo(); 
t.getBook('cool'); 

此輸出:

cool/part1/section1/chapter1 
cool/part1/section1/chapter2 
cool/part1/section2/chapter1 
cool/part1/section2/chapter2 
cool/part2/section1/chapter1 
cool/part2/section1/chapter2 
cool/part2/section2/chapter1 
cool/part2/section2/chapter2 
+0

我明白你在說什麼,但我真的很喜歡這本書本身從可觀察到的(發射而非章,我想成爲書籍結構的一部分)。我希望返回observable返回的方法就是這本書,它只是需要在這樣做之前遞歸地'解析'一些字段。 –

+0

特別是,我不希望這本書在它完全形成之前從觀察者中發出。我正在訂閱來自解析器的'getBook(name)',並且我不想在加載數據之前加載頁面。 –

+0

您可以採用上述結構並將'.toArray()'添加到結尾。這將在繼續前進之前將所有結果收集到一個數組中。在巫婆之後,您可以使用'.map(...)'來重新組合它,但是您需要。 – Graztok