2017-09-06 6 views
0

Angular/TypeScriptで2つのHTTP get検索をマージしようとしていますが、動作させるのに問題があります。Angular Heroesチュートリアルで2つの検索をマージするには?

Observableを使って英雄を "name"値(https://angular.io/tutorial/toh-pt6#add-the-ability-to-search-by-name)で検索する、Angular 2/4 Tour of Heroesチュートリアルを使って状況を示しています。次のようにヒーロー・search.service.tsのコードは次のとおりです。

import { Injectable } from '@angular/core'; 
import { Http }  from '@angular/http'; 

import { Observable }  from 'rxjs/Observable'; 
import 'rxjs/add/operator/map'; 

import { Hero }   from './hero'; 

@Injectable() 
export class HeroSearchService { 

    constructor(private http: Http) {} 

    search(term: string): Observable<Hero[]> { 
    return this.http 
       .get(`api/heroes/?name=${term}`) 
       .map(response => response.json().data as Hero[]); 
    } 
} 

私はヒーロークラスに「同義語」の2番目の文字列値を追加するのと同等の操作を行う必要があります

export class Hero { 
    id: number; 
    name: string; 
    synonym: string; 
} 

と各ヒーローに同義語を追加します。

import { InMemoryDbService } from 'angular-in-memory-web-api'; 
export class InMemoryDataService implements InMemoryDbService { 
    createDb() { 
    const heroes = [ 
     { id: 0, name: 'Zero', synonym: 'little' }, 
     { id: 11, name: 'Mr. Nice', synonym: 'pleasant' }, 
     { id: 12, name: 'Narco', synonym: 'sleep' }, 
     { id: 13, name: 'Bombasto', synonym: 'loud' }, 
     { id: 14, name: 'Celeritas', synonym: 'vegetable' }, 
     { id: 15, name: 'Magneta', synonym: 'color' }, 
     { id: 16, name: 'RubberMan', synonym: 'hose' }, 
     { id: 17, name: 'Dynama', synonym: 'motor' }, 
     { id: 18, name: 'Dr IQ', synonym: 'smart' }, 
     { id: 19, name: 'Magma', synonym: 'volcanic' }, 
     { id: 20, name: 'Tornado', synonym: 'wind' } 
    ]; 
    return {heroes}; 
    } 
} 

私は、代入することにより同義語でヒーロー・search.service.tsで検索することができます。

 .get(`api/heroes/?synonym=${term}`) 

私の質問は、名前とシノニムの両方を検索し、名前またはシノニムのどちらかで一致を返す方法です。

ReactiveXのドキュメントからは、答えがマージ演算子:http://reactivex.io/documentation/operators/merge.htmlを使用するように思われます。しかし、私はこれを動作させるのに問題があります。

import { Injectable } from '@angular/core'; 
import { Http }  from '@angular/http'; 

import { Observable }  from 'rxjs/Observable'; 
import 'rxjs/add/operator/map'; 
import 'rxjs/add/operator/merge'; 

import { Hero }   from './hero'; 

@Injectable() 
export class HeroSearchService { 

    constructor(private http: Http) {} 

    search(term: string): Observable<Hero[]> { 
    const nameResults = this.http.get(`api/heroes/?name=${term}`); 
    const synonymResults = this.http.get(`api/heroes/?synonym=${term}`);  
    nameResults.merge(synonymResults); 
    return nameResults.map(response => response.json().data as Hero[]); 
    } 
} 

ないワーキング・適切にコードがhttps://plnkr.co/edit/4mrL5ReQCSvuzOODixJU?p=previewである:私は上記の英雄search.service.tsコードの次の新しいバージョンを含む、マージ使用してのさまざまな方法を試してみました。

マージが成功したというエビデンスは表示されず、nameResultsはシノニムではなく名前のみを指定します。エラーメッセージは表示されません。

http://reactivex.io/documentation/operators/merge.htmlでRxJSコードは、フォーム

const mergedResults = Rx.Observable.merge(nameResults, synonymResults); 

のコードを使用していますが、私はそのようなコードを試してみたときに、私はエラーを取得するには、フラグを立て:

は 'Rxの'

を名前を見つけることができません

私の質問は以下の通りです:

どのようにRxJSマージここに?

もっと適切なRxJSを使用して他のアプローチがありますか?

Hero配列の各行にnamePlusSynonymを追加することなくnamePlusSynonymを計算するなど、Heroクラスのレベルで他のアプローチがありますか?

追加:ここに示唆したコードとhttp://reactivex.io/rxjs/class/es6/Observable.js~Observable.html#instance-method-mergeにコードを記入しました。コンソール出力を備えた新しいバージョンのhero-search.service.tsを作成しました。

import { Injectable } from '@angular/core'; 
import { Http } from '@angular/http'; 

import { Observable } from 'rxjs/Observable'; 
import 'rxjs/add/operator/map'; 
import 'rxjs/add/operator/merge'; 

import { Hero } from './hero'; 

@Injectable() 
export class HeroSearchService { 

    constructor(private http: Http) {} 

    search(term: string): Observable<Hero[]> { 
    const nameResults = this.http.get(`api/heroes/?name=${term}`); 
    nameResults.subscribe(nameData => console.log('nameData', nameData)); 
    const synonymResults = this.http.get(`api/heroes/?synonym=${term}`); 
    synonymResults.subscribe(synonymData => console.log('synonymData', synonymData)); 
    const combinedResults = nameResults.merge(synonymResults); 
    combinedResults.subscribe(combinedData => console.log('combinedData', combinedData)); 
    return combinedResults.map(response => response.json().data as Hero[]); 
    } 
} 

ただし、nameResultsではなくsynonymResultsのみが表示されます。 nameResultsとsynonymResultsはどちらもコンソールの出力でOKですが、combineResultsはデータとシノニム結果のURLのみを持ち、マージメソッドの影響を受けていないようです。

私も同様の結果を得て、連結で試しました。

それは私が右の段階で組み合わせることが、異なる段階で組み合わせることと同じ結果が得られる、唯一の同義語を示すないよようだ:

search(term: string): Observable<Hero[]> { 
    const nameResults = this.http.get(`api/heroes/?name=${term}`).map(response => response.json().data as Hero[]); 
    nameResults.subscribe(nameData => console.log('nameData', nameData)); 
    const synonymResults = this.http.get(`api/heroes/?synonym=${term}`).map(response => response.json().data as Hero[]); 
    synonymResults.subscribe(synonymData => console.log('synonymData', synonymData)); 
    const combinedResults = nameResults.merge(synonymResults); 
    combinedResults.subscribe(combinedData => console.log('combinedData', combinedData)); 
    return combinedResults; 
    } 
+0

2つのHTTPリクエストを使用してクライアント側でマージするのは少し珍しいようです。通常、私は 'api/heroes?synonym = $ {synonym}&name = $ {name}'のようなものを見たいと思うでしょう。しかし、あなたが欠けているものは、 'nameResults = nameResults.merge(synonymResults);'あなたがマージしたオブザーバブルであるmergeからのリターンを無視していることです。 – Pace

+0

また、 'let combinedResults = nameResults.merge(synonymResults)'を呼び出し、 'combinedResults.map(...) 'を返します。 – Pace

+0

最後の2行を' const combinedResults = nameResults'に変更します。マージ(synonymResults); return combinedResults.map(response => response.json()。data Hero []); '結果は同義語ではあるが名前ではない。 –

答えて

0

マージオペレータが動作するように取得するには、次のようにする必要がありそれはplunkerであるのと同様に、観察可能なインポートしrxjsからマージ:

import { Observable } from 'rxjs/Observable'; 
import 'rxjs/add/operator/merge'; 

がどのように使用rxJSがここに合流することができますか?

私はここにあなたの主な誤解が観測戻り 新しいマージされた観察可能なmerge()を呼び出すことだと思います。 rxjs機能が pureであるため、ここでそれを呼び出すと namedResults

nameResults.merge(synonymResults); 

を変異させていない代わりに、新しい定数

const combinedResults = nameResults.merge(synonymResults); 
return combinedResults; 

で結果を取得する必要があり、よりあるRxJSを使用して他のいくつかのアプローチがあります適切な?

これは私だけhero-search.service.tsを変更し、それは既存の角度成分を変更することなく動作させるために、問題(plunker hereを)解決する方法です。演算子を連鎖させることで、これをもっとうまく見せることができますが、各段階で型を持つ有用な変数名を見ることは、学習に非常に役立つと思います。テストのために中間値subscribe() & console.log()を観測値のいずれかに置くと、値が実際にどのように見えるかを知ることができます。

search(term: string): Observable<Hero[]> { 
    // get the response observable from requesting the backend  
    const nameResults: Response = this.http.get(`api/heroes/?name=${term}`); 
    // boil that response down to just the data array we care about 
    const nameResultsArr: Observable<Hero[]> = nameResults.map(res => res.json().data); 
    // do the same for the synonym request 
    const synonymResults: Response = this.http.get(`api/heroes/?synonym=${term}`); 
    const synonymResultsArr: Observable<Hero[]> = synonymResults.map(res => res.json().data); 

    // combine the two observable arrays into a stream of arrays 
    const combinedHeroListObservables: Observable<Hero[]> = 
    nameResultsArr.merge(synonymResultsArr); 
    // concat the observable arrays onto each other 
    const concatenatedArrays: Observable<Hero[]> = 
    combinedHeroListObservables.reduce((accumulator, current) => accumulator.concat(current)); 

    // return the combined array 
    return concatenatedArrays; 
} 

が、私はそのようなコードを試したとき、私はエラーがフラグを立てられ得る: Cannot find name 'Rx'

をあなたは不あなたが使用していない事をインポートする気にしないのであれば、あなたはこれを取得することができますそれが唯一の事業者/ plunkerの例に見られるように、あなたが必要とするタイプをインポートすることをお勧めし、

import * as Rx from 'rxjs/Rx'; 

と協力しかし。

PS:コメントで言われたように、両方の結果を組み合わせて返すような安心のルートがあれば、クライアントはサーバーに2回往復する必要はありません。しかし、Angularチームの例を使用しているため、これを実際に行うことはできません。

+0

詳細な対応をありがとうございます。これは実際にはPlunkerで実行されますが、VSCodeに入れたときに私は8つのエラーが発生し、プログラムは起動しません。 nameResultsにタイプ 'Observable 'とフラグが立てられていますが、タイプ 'Response'に割り当てられません。プロパティ 'body'がタイプ 'Observable 'にありません。 マップに 'Map'というプロパティがフラグされていますが、タイプ 'Response'には存在しません。 const combinedHeroListObservables:Observable []> = nameResultsArr.merge(synonymResultsArr);コンストラクタの概要 –

+0

combinedHeroListObservablesに 'Observable 'というタイプのフラグが設定されていますが、 'Observable []>'タイプに割り当てられません。 タイプ 'Hero []'はタイプ 'Observable []'に割り当てられません。 タイプ 'Hero'はタイプ 'Observable 'に割り当てられません。 プロパティ '_isScalar'がタイプ 'Hero'にありません。 –

+0

そして私は 'rxjs/add/observable/from'をインポートするかどうかわかりません。必要とされるか、何か他のものから残される。 –

関連する問題