2016-02-23 25 views
11

私は入力フィールドを持っており、ユーザーが検索文字列を入力すると、_heroService httpリクエストを行う前にユーザーが少なくとも300ミリ秒(debounce)の入力を待つことを望みます。変更された検索値のみがサービスに渡されます(distinctUntilChanged)。 switchMapは、これらの_heroServiceオブザーバブルを結合し、元のリクエスト順でそれらを再配置し、最新の検索結果のみをサブスクライバに配信する新しいオブザーバブルを返します。Angular2 @ TypeScript Observableエラー

私はAngular 2.0.0-beta.0とTypeScript 1.7.5を使用しています。

どうすればこの問題を解決できますか?

EXCEPTION: TypeError: unknown type returned 
STACKTRACE: 
TypeError: unknown type returned 
at Object.subscribeToResult (http://localhost:3000/rxjs/bundles/Rx.js:7082:25) 
at SwitchMapSubscriber._next (http://localhost:3000/rxjs/bundles/Rx.js:5523:63) 
at SwitchMapSubscriber.Subscriber.next (http://localhost:3000/rxjs/bundles/Rx.js:9500:14) 
... 
-----async gap----- Error at _getStacktraceWithUncaughtError 
EXCEPTION: Invalid argument '[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]' for pipe 'AsyncPipe' in [heroes | async in [email protected]:16] 

test1.ts

import {bootstrap}   from 'angular2/platform/browser'; 
import {Component}   from 'angular2/core'; 
import {HTTP_PROVIDERS} from 'angular2/http'; 

import {Observable}  from 'rxjs/Observable'; 
import {Subject}   from 'rxjs/Subject'; 
import 'rxjs/Rx'; 

import {Hero}    from './hero'; 
import {HeroService}  from './hero.service'; 

@Component({ 
    selector: 'my-app', 
    template: ` 
     <h3>Test</h3> 
     Search <input #inputUser (keyup)="search(inputUser.value)"/><br> 
     <ul> 
      <li *ngFor="#hero of heroes | async">{{hero.name}}</li> 
     </ul> 
    `, 
    providers: [HeroService, HTTP_PROVIDERS] 
}) 

export class Test { 

    public errorMessage: string; 

    private _searchTermStream = new Subject<string>(); 

    private heroes: Observable<Hero[]> = this._searchTermStream 
     .debounceTime(300) 
     .distinctUntilChanged() 
     .switchMap((value: string) => 
      this._heroService.searchHeroes(value) 
       .subscribe(
        heroes => this.heroes = heroes, 
        error => this.errorMessage = <any>error) 
     ) 

    constructor (private _heroService: HeroService) {} 

    search(value: string) { 
     this._searchTermStream.next(value); 
    } 
} 

bootstrap(Test); 

hero.ts:(検索入力フィールドの最初のキーを入力した後に)

Error:(33, 20) TS2345: Argument of type '(value: string) => Subscription<Hero[]>' is not assignable to parameter of type '(x: {}, ix: number) => Observable<any>'.Type 'Subscription<Hero[]>' is not assignable to type 'Observable<any>'. Property 'source' is missing in type 'Subscription<Hero[]>'. 
Error:(36, 31) TS2322: Type 'Hero[]' is not assignable to type 'Observable<Hero[]>'. Property 'source' is missing in type 'Hero[]'. 

実行時エラー:

私はコンパイルエラーを取得します

export interface Hero { 
    _id: number, 
    name: string 
} 

hero.service.ts

import {Injectable}  from 'angular2/core'; 
import {Http, Response} from 'angular2/http'; 
import {Headers, RequestOptions} from 'angular2/http'; 
import {Observable}  from 'rxjs/Observable'; 
import 'rxjs/Rx'; 

import {Hero}   from './hero'; 

@Injectable() 

export class HeroService { 

    private _heroesUrl = 'api/heroes'; 

    constructor (private http: Http) {} 

    getHeroes() { 
     return this.http.get(this._heroesUrl) 
      .map(res => <Hero[]> res.json()) 
      .do(data => console.log(data)) 
      .catch(this.handleError); 
    } 

    searchHeroes (value) { 
     return this.http.get(this._heroesUrl + '/search/' + value) 
      .map(res => <Hero[]> res.json()) 
      .do(data => console.log(data)) 
      .catch(this.handleError); 
    } 

    addHero (name: string) : Observable<Hero> { 

     let body = JSON.stringify({name}); 
     let headers = new Headers({ 'Content-Type': 'application/json' }); 
     let options = new RequestOptions({ headers: headers }); 

     return this.http.post(this._heroesUrl, body, options) 
      .map(res => <Hero> res.json()) 
      .do(data => console.log(data)) 
      .catch(this.handleError) 
    } 

    private handleError (error: Response) { 
     // in a real world app, we may send the server to some remote logging infrastructure 
     // instead of just logging it to the console 
     console.log(error); 
     return Observable.throw('Internal server error'); 
    } 
} 

のindex.htmlここ

<!DOCTYPE html> 
<html> 
    <head> 
    <base href="/"> 
    <script src="angular2/bundles/angular2-polyfills.js"></script> 
    <script src="typescript/lib/typescript.js"></script> 
    <script src="systemjs/dist/system.js"></script> 
    <script src="angular2/bundles/router.dev.js"></script> 
    <script src="rxjs/bundles/Rx.js"></script> 
    <script src="angular2/bundles/angular2.js"></script> 
    <script src="angular2/bundles/http.dev.js"></script> 
    <link rel="stylesheet" href="node_modules/bootstrap/dist/css/bootstrap.min.css"> 
    <script> 
     System.config({ 
     transpiler: 'typescript', 
     typescriptOptions: { emitDecoratorMetadata: true }, 
     packages: {'components': {defaultExtension: 'ts'}} 
     }); 
     System.import('components/test1') 
      .then(null, console.error.bind(console)); 
    </script> 
    </head> 
    <body> 
    <my-app>Loading...</my-app> 
    </body> 
</html> 

ある別のバージョンごとに(からkeyup)イベントの後httpリクエストをして正常に動作します 'test2.ts':

import {bootstrap}   from 'angular2/platform/browser'; 
import {Component}   from 'angular2/core'; 
import {HTTP_PROVIDERS} from 'angular2/http'; 

import {Hero}    from './hero'; 
import {HeroService}  from './hero.service'; 

@Component({ 
    selector: 'my-app', 
    template: ` 
     <h3>Test</h3> 
     Search <input #inputUser (keyup)="search(inputUser.value)"/><br> 
     <ul> 
      <li *ngFor="#hero of heroes">{{hero.name}}</li> 
     </ul> 
    `, 
    providers: [HeroService, HTTP_PROVIDERS] 
}) 

export class Test { 

    public heroes:Hero[] = []; 
    public errorMessage: string; 

    constructor (private _heroService: HeroService) {} 

    search(value: string) { 
     if (value) { 
      this._heroService.searchHeroes(value) 
       .subscribe(
        heroes => this.heroes = heroes, 
        error => this.errorMessage = <any>error); 
     } 
     else { 
      this.heroes = []; 
     } 
    } 
} 

bootstrap(Test); 
+0

角度2のリファレンスはベータ版ではないため、アップグレードするとうまくいくかもしれません – bilpor

答えて

17

.subscribe(...)は、Observableではなく、Subscriptionを返します。 subscribe(...)を削除するか、.map(...)に置き換え、値にアクセスするときは.subscribe(...)を使用してください。

+0

ありがとうございました。 少し具体的になりますか?観察可能なものは私にとっては非常に困難です。 '.subscribe(..)'ブロックはどこに置くのですか? –

+0

多くのコードを提供しましたが、私は完全に調査しませんでした。私は '* ngFor ="英雄の#ヒーロー| async "で動作するはずの' * ngFor = "#英雄ヒーロー"を見つけました。asyncはあなたのために 'subscribe()'を行います。 'this.heroes.subscribe(...)'。 –

+0

あなたの忍耐をありがとう、私は初心者です;-) 「this.heroes.subscribe(...)」をどこにどのくらい正確に入れますか? ライフサイクルフック 'ngOnChanges(){this.heroes.subscribe(...)}'を実行したとしますが、実行時エラーが発生します: 'EXCEPTION:[object in]がサポートされていません。エラー:(39,23)TS2322: 'Hero []'タイプが 'Observable 'タイプに割り当てられません。タイプ 'Hero []'にプロパティ 'source'がありません。 ' –

関連する問題