我想在Angular/TypeScript中合併2個HTTP獲取搜索,但我無法正常工作。如何在Angular Heroes教程中合併2個搜索?
使用Angular 2/4 Tour of Heroes教程來說明情況,該教程使用Observable通過「name」值搜索英雄(https://angular.io/tutorial/toh-pt6#add-the-ability-to-search-by-name)。在英雄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[]);
}
}
我需要做添加第二個字符串值「代名詞」的英雄類相當於:
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。但是,我無法使其工作。我試着使用合併,包括上面的英雄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}`);
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。
我沒有看到任何合併成功的證據,並且nameResults僅給出名稱,而不給出同義詞。沒有錯誤消息出現。
在http://reactivex.io/documentation/operators/merge.html的RxJS代碼使用形式
const mergedResults = Rx.Observable.merge(nameResults, synonymResults);
的代碼,但是當我嘗試這樣的代碼我得到一個錯誤標記:
找不到名稱 'RX'
所以我的問題是:
如何使用RxJS merg在這裏?
有沒有其他方法使用RxJS更適合?
有沒有其他的方法可以在Hero類中工作,比如計算namePlusSynonym而不必爲Hero數組中的每一行添加namePlusSynonym?
附錄:下面的建議和代碼在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[]);
}
}
但它只顯示synonymResults,而不是nameResults。 nameResults和synonymResults在控制檯輸出中對我看起來不錯,但combinedResults只有數據和同義詞結果的URL,並且似乎不受合併方法的影響。
我也嘗試與concat,具有類似的結果。
看來,我不是在合適的階段組合,但在不同階段結合的結果相同,只顯示同義詞:
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;
}
使用兩個HTTP請求然後在客戶端合併它們似乎有點不尋常。通常我會期望看到類似'api/heroes?synonym = $ {synonym}&name = $ {name}'的東西。然而,我認爲你缺少的一件事是'nameResults = nameResults.merge(synonymResults);'你忽略了合併的返回值,這是合併的觀察值。 – Pace
或者更好的辦法是:'let combinedResults = nameResults.merge(synonymResults)',然後返回'combinedResults.map(...)' – Pace
將最後兩行改爲:const combinedResults = nameResults。合併(synonymResults); return combinedResults.map(response => response.json()。data as Hero []);'結果在同義詞工作,但不是名稱。 –