2017-12-26 36 views
0

エンティティの詳細を取得する必要があります。私も著者と出版社のデータを取得するよう ブックオブジェクトは、この角度で観測可能なものを連結する

{ 
    title: XYZ, 
    published: XYZ 
    author: URL_TO_ENDPOINT 
    publisher: URL_TO_ENDPOINT 
} 

のようになります。今、私はチェーン約束する必要があります。私はgetResourceByURLメソッドを実装し、簡単なApiServiceを持っている、と私は、これは私がまさに私のオブジェクトを知っている限り、簡単です 私ApiServiceとチェーンpromicesを呼び出し、新しいサービスDetailsS​​erviceを作成:

return this.apiService.getResourceByURL(book.url).flatMap((entity) => { 
    return Observable.forkJoin(
    Observable.of(entity), 
    this.apiService.getResourceByURL(entity.author) 
    this.apiService.getResourceByURL(entity.publisher) 
).map(entityFullDetails => { 
    let entity = entityFullDetails[0]; 
    let author = entityFullDetails[1]; 
    let publisher = entityFullDetails[2]; 
    entity.author = author; 
    entity.publisher = publisher; 
    return entity; 
    }); 
}); 

問題は、私が使用していたということですAuthor/Publishersの詳細を取得できるようにするために、DetailsS​​erviceの同じメソッドを使用します。つまり、エンティティオブジェクトのすべてのキーを反復処理し、そのキーの値がURLであればapiService.getResourceByURLを呼び出す必要があります)。

簡単にできますか?または抽象度を下げて、BookDetail、AuthorDetailなどを取得するための別のメソッドを用意する必要があります。

私は1つのレベルのネストだけに興味があります。私はこの本の著者をフェッチする場合、私は、私は罰金あなただけの必要を行う関数を書くことができます

+0

あなただけの観測で作業しているとき、なぜあなたは約束を話していますか? –

+0

[Angular 2 - Chaining http要求]の重複している可能性があります(https://stackoverflow.com/questions/42626536/angular-2-chaining-http-requests) –

+0

@ Jota.Toledo重複して私を攻撃しません。少なくともその質問にはならない。ここでのOPは、要求を連鎖させる方法を知っています。返されるリソースの構造を知らなくても、プロセスを自動化することだけです。 –

答えて

0

をループを防止するために

{ 
    title: XYZ, 
    published: XYZ 
    author: {name: XXX, country: XXX, books: [URL, URL, URL], ...} 
    ... 
} 

のようなものを取得しています意味その著者によって書かれたすべての書籍を取得する必要がないことを意味物事は自動的に。これは実際には再帰的に動作しますが、これを特に避けたい場合は、getResourceByURLを呼び出すことによって再帰呼び出しをそれ自体に置き換えてください。

const createFakeResponse = url => { 
 
    switch (url) { 
 
    case 'http://book': return { 
 
     name: 'The rxjs Book', 
 
     author: 'http://author', 
 
     publisher: 'http://publisher', 
 
    }; 
 

 
    case 'http://author': return { 
 
     name: 'John Doe', 
 
     numberOfBooks: 'http://numberOfBooks' 
 
    }; 
 

 
    case 'http://publisher': return 'ACME Publishing Corp.'; 
 
    case 'http://numberOfBooks': return 42; 
 
    } 
 
}; 
 

 
// Fake the HTTP calls with some delay 
 
const getResourceByURL = url => Rx.Observable 
 
    .of(createFakeResponse(url)) 
 
    .do(() => console.log('HTTP call: ', url)) 
 
    .delay(1000 * Math.random()); 
 

 
// Determines whether this key in the resource has to be fetched from its URL 
 
const isReference = ([key, value]) => value.startsWith('http://'); 
 

 
const fetchWithReferences = url => getResourceByURL(url) 
 
    .do(resource => console.log('Raw resource: ', resource)) 
 
    .flatMap(resource => { 
 
     // Find all keys for which the corresponding value is 
 
     // a reference that we need to resolve. 
 
     const referenceKeys = Object.entries(resource) 
 
     .filter(isReference) 
 
     .map(([key]) => key); 
 

 
     return Rx.Observable 
 
     .forkJoin(
 
      Rx.Observable.of(resource), 
 
      ...referenceKeys.map(key => fetchWithReferences(resource[key])) 
 
     ) 
 
     .map(([resource, ...resources]) => Object.assign(resource, ...resources.map((current, index) => { 
 
      // This uses computed property names 
 
      return { [referenceKeys[index]]: current }; 
 
     }))); 
 
    }); 
 

 
console.log('Starting...'); 
 
fetchWithReferences('http://book') 
 
    .map(result => JSON.stringify(result, null, 2)) 
 
    .subscribe(result => console.log('Final result: ', result));
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/5.5.6/Rx.min.js"></script>

+0

ありがとうございました。 – Chaki

関連する問題