6

Could you tell me how can I return Observable here? I have tried many ways. But no success yet.

[ts] A function whose declared type is neither 'void' nor 'any' must return a value.

  deleteInvite(inviteId):Observable<HttpResponse<Object>> {
    this.getHttpHeader().then(headers => {
      return this.http.post(this.apiURL + "/deleteInvite", inviteId, { observe: "response", headers: headers })
    }).catch(err => {
      console.error(err);
    });
  }

  async getHttpHeader() {
    const accessToken = await this.getJWTToken();
    let headers = new HttpHeaders().set('Authorization', `Bearer ${accessToken}`);
    return headers;
  }
Sampath
  • 63,341
  • 64
  • 307
  • 441

2 Answers2

11

FOR rxjs version: 6.0.0 onwards

import { from } from 'rxjs';

 deleteInvite(inviteId):Observable<HttpResponse<Object>> {
    return from(this.getHttpHeader()).pipe(
        switchMap(headers => {
            return this.http.post(this.apiURL + "/deleteInvite", inviteId, { observe: "response", headers: headers })
        }),
        catchError(err => {
            console.error(err);
        })
    );
}

For older versions of rxjs:

Convert the thisGetHeaders() to an Observable by using fromPromise

import { fromPromise } from 'rxjs/observable/fromPromise';


deleteInvite(inviteId):Observable<HttpResponse<Object>> {
    return fromPromise(this.getHttpHeader()).pipe(
        switchMap(headers => {
            return this.http.post(this.apiURL + "/deleteInvite", inviteId, { observe: "response", headers: headers })
        }),
        catchError(err => {
            console.error(err);
        })
    );
}
Suraj Rao
  • 29,388
  • 11
  • 94
  • 103
  • It gives this error: `[ts] The 'this' context of type 'void' is not assignable to method's 'this' of type 'Observable<{}>'.` – Sampath Jun 15 '18 at 13:30
  • could be related to your rxjs operators.. https://stackoverflow.com/questions/47198706/rxjs-pipe-and-lettable-operator-map-this-context-of-type-void-is-not-assi which is the version you are using? – Suraj Rao Jun 15 '18 at 13:36
  • `"rxjs": "5.5.2",` `import { Observable } from 'rxjs/Observable'; import { fromPromise } from 'rxjs/observable/fromPromise'; import { switchMap } from 'rxjs/operator/switchMap';` Any clue? – Sampath Jun 15 '18 at 13:39
  • change to `import { switchMap } from 'rxjs/operators'` – Suraj Rao Jun 15 '18 at 13:41
  • Now, this error: `[ts] Argument of type '{ observe: "response"; headers: void | HttpHeaders; }' is not assignable to parameter of type '{ headers?: HttpHeaders | { [header: string]: string | string[]; }; observe?: "body"; params?: Ht...'. Types of property 'headers' are incompatible. Type 'void | HttpHeaders' is not assignable to type 'HttpHeaders | { [header: string]: string | string[]; }'. Type 'void' is not assignable to type 'HttpHeaders | { [header: string]: string | string[]; }'.` – Sampath Jun 15 '18 at 13:42
  • check the return of `getHttpHeader()` .. the header parameter is showing incompatible type – Suraj Rao Jun 15 '18 at 13:44
  • Here it is: `(method) CommonProvider.getHttpHeader(): Promise` – Sampath Jun 15 '18 at 13:45
  • It seems `return this.http.post(this.apiURL + "/deleteInvite", inviteId, { observe: "response", headers: headers })` here `headers` is not being identified by the TS. This thing here `switchMap(headers => {` Any clue? – Sampath Jun 15 '18 at 13:49
  • if your function doesnt actually return void, you can force type like `headers` – Suraj Rao Jun 15 '18 at 13:50
  • That is it. Thanks a lot :) – Sampath Jun 15 '18 at 13:53
  • Note: As of rxjs 6.0.0-beta.3, operators and observable creators should be imported from rxjs. Furthermore, fromPromise is not part of the public API anymore and its wrapped in the from method. https://stackoverflow.com/questions/45784825/frompromise-does-not-exist-on-type-observable – Vincent V. Nov 18 '19 at 20:47
0

getHttpHeader() returns a Promise. Just wait for it to unwrap its value. Then return the result of this.http.post which is the expected Observable. For that, use the await keyword inside a try/catch block:

async deleteInvite(inviteId) {
    try {
        const headers = await this.getHttpHeader();
        return this.http.post(this.apiURL + "/deleteInvite", inviteId, { observe: "response", headers: headers });
    }
    catch (err) {
        console.error(err);
    }
}

Then do await deleteInvite(inviteId) on the consumer side to handle the returned Promise.

Still, mixing Observable and Promise are complicated. Do all with Promises (or all Observables) can be easier : "return await this.http.post().toPromise()".

Romain Deneau
  • 2,841
  • 12
  • 24
  • I need to return `Observable` form this method `deleteInvite()`. But with your implementation where it returns `Promise` due to `async`. – Sampath Jun 15 '18 at 11:50
  • `this.http.post` will return an observable. You will have to convert this to a promise using `Observable.toPromise` – Suraj Rao Jun 15 '18 at 12:16
  • @Sampath: you're right. Using `async`/`await` is just a bit clearer. But we cannot unwrap the `Promise` returned by `deleteInvite` directly but another `await`: ` deleteInvite()` on the consumer side. The code is easier to read than with all the rxjs helper scaffolding. – Romain Deneau Jun 15 '18 at 14:34