Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Property 'then' does not exist on type Observable

Tags:

I'm new to angular 2 and I'm trying to make a REST GET request, but I'm getting this error when trying:

error TS2339: Property 'then' does not exist on type 'Observable<Connection[]>'.

Here is the component calling the service:

import { Component, OnInit} from '@angular/core';
import { Router }           from '@angular/router';

import { Connection }       from './connection';
import { ConnectionService }      from './connection.service';

let $: any = require('../scripts/jquery-2.2.3.min.js');

@Component({
  selector: 'connections',
  styleUrls: [ 'connections.component.css' ],
  templateUrl: 'connections.component.html',
  providers: [ConnectionService]
})

export class ConnectionsComponent implements OnInit {

  connections: Connection[];
  selectedConnection: Connection;

  constructor(
    private connectionService: ConnectionService,
    private router: Router) { }

  getConnections(): void {
    this.connectionService.getConnections().then(connections => {
      this.connections = connections;
    });
  }

  ngOnInit(): void {
    this.getConnections();
  }

  onSelect(connection: Connection): void {
    this.selectedConnection = connection;
  }

  gotoDetail(): void {
    this.router.navigate(['/connectiondetail', this.selectedConnection.id]);
  }
}

Here is the ConnectionService:

import { Injectable }     from '@angular/core';
import { Http, Response } from '@angular/http';
import { Connection }     from './connection';
import { Observable }     from 'rxjs/Observable';

@Injectable()
export class ConnectionService {

  private connectionsUrl = 'https://localhost/api/connections';  // URL to web API

  constructor (private http: Http) {}

  getConnections(): Observable<Connection[]> {
    return this.http.get(this.connectionsUrl)
                    .map(this.extractData)
                    .catch(this.handleError);
  }

  private extractData(res: Response) {
    let body = res.json();
    return body.data || { };
  }

  private handleError (error: Response | any) {
    // In a real world app, we might use a remote logging infrastructure

    let errMsg: string;

    if (error instanceof Response) {
      const body = error.json() || '';
      const err = body.error || JSON.stringify(body);
      errMsg = `${error.status} - ${error.statusText || ''} ${err}`;
    } else {
      errMsg = error.message ? error.message : error.toString();
    }

    console.error(errMsg);

    return Observable.throw(errMsg);
  }
}

How do I fix this error?

Thank you,

Tom

like image 260
Thomas Kessler Avatar asked Dec 06 '16 00:12

Thomas Kessler


1 Answers

An Observable doesn't have a promise-like method as then. In your service you are performing an http call which returns an Observable and you map this Observable to another Observable.

If you really want to use the promise-style API, you need to convert your Observable to a promise using the toPromise operator. This operator is not available by default so that you also need to import it once in your project.

import 'rxjs/add/operator/toPromise';

Using promises is okay, but there are some good reasons to use the Observable APIs directly. For details, please see this blog post advertising the usage of Observables.

If you want to use the Observable API directly then replace your then call with a subscribe call. But remember that every subscription also needs to be cancelled when your component gets destroyed.

getConnections(): void {
  this.subscription = this.connectionService.getConnections()
    .subscribe(connections => this.connections = connections);
}

ngOnDestroy() {
  this.subscription.unsubscribe();
}

Another option when working with Observables is to assign the resulting Observable to a field in your component and then use the async pipe. Doing so, Angular will handle the subscriptions for you.

like image 53
Andreas Jägle Avatar answered Sep 29 '22 21:09

Andreas Jägle