2

I have a service with some properties, which to be initialized before any component load (they used as parameters to other http calls). Route CanActivate method used to call the following method, which should retrieve true after properties initialized, or false on error. I receive compilation error: A function whose declared type is neither 'void' nor 'any' must return a value. How I can avoid this error?

public setupSession(): boolean {

    this._http.get('myservice_url')
    .map (
        (response: Response) => <any>response.json())
        .subscribe (
        data => {
            this.property1 = data.property1;
            this.property2 = data.property2;
            return true;
        },
        err => {
            console.error(err)
            return false;
        }
    )
}

Edit: @K. Daniek thanks for help! I found solution with help of this article link. Now I can ensure setup complete before any other http call.

The service method:

public setupSession(): Promise<any> {
    var observable = this._http.get('myservice_url')
        .map((response: Response) => {
            var res = response.json();
            return res;
        });

    observable.subscribe(data => {
        this.property1 = data.property1;
        this.property2 = data.property2;
    });

    return observable.toPromise();
}

canActivate method:

canActivate() {
    return this._sessionService.setupSession().then(() => {
        return true;
    });
}
Community
  • 1
  • 1
Victor
  • 121
  • 1
  • 8

1 Answers1

0

I don't see the point to declare type of this function as boolean, especially when the return of this function is actually data, not a boolean value.

Try following code:

public setupSession() {

  this._http.get('myservice_url')
    .map(
    (response: Response) => <any>response.json())
    .subscribe(
    data => {
        this.property1 = data.property1;
        this.property2 = data.property2;
    },
    err => {
        console.error(err);
    }
    )
}

Edit: I was testing your code a little bit and just realized that it is actually possible to make this function work, but you have to basically return a boolean value after subscribe method. The refactored code would look like:

public setupSession(): boolean {

    this._http.get('myservice_url')
        .map(
            (response: Response) => <any>response.json())
        .subscribe(
            data => {
                this.property1 = data.property1;
                this.property2 = data.property2;
            },
            err => {
                console.error(err);
            });
    return true;

}

Now your http request function returns a boolean value, compiler won't throw any errors.

Edit2:

Listen, if you want this function to be boolean type, you have to return a boolean value after calling the function. Because of the fact, that this call is asynchronous, the function continues to execute other tasks inside and doesn't wait for the asynchronous response. That's why the function will always return true (in this particular case), even before returning success or error response.

If you want the function to return true in case of success or false in case of error, use following code:

public setupSession() {

    this.http.get(`myservice_url`)
        .map(data => data.json())
        .subscribe(data => {
                this.property1 = data.property1;
                this.property2 = data.property2;
                console.log('works');
                return true;
            },
            err => {
                console.error(err);
                console.log('error);
                return false;
            });
}
kind user
  • 40,029
  • 7
  • 67
  • 77
  • In this case how I can retrieve canActivate value? If I dont use canActivate , then the properties will not be initialized before I use them as parameters to other http calls. – Victor Jan 04 '17 at 21:56
  • In second case you retrieve boolean before actual data received. – Victor Jan 04 '17 at 22:02
  • In the third case I get compilation error in canActivate: canActivate() { if (this._sessionService.isSessionSetup) return true; return this._sessionService.setupSession(); } – Victor Jan 04 '17 at 22:15
  • "No best common type exists among return expressions" – Victor Jan 04 '17 at 22:21
  • Edited my third code, try it and tell me if it works. – kind user Jan 04 '17 at 22:34
  • 1
    @Victor Don't give up dude. – kind user Jan 05 '17 at 00:24
  • I don't see any difference. When I call this method, it returns undefined value. Is there a way to make synchronous http call? I don't believe canActivate function is designed just to check some property? To identify access to some area sometimes you have first to check database settings. Thanks for help! – Victor Jan 05 '17 at 14:55
  • I initialized data with APP_INITIALIZER – Victor Jan 05 '17 at 15:59
  • @Victor I will try to help you when I'm back from my work. – kind user Jan 05 '17 at 16:02
  • @Victor Plunker would be much helpful, but anyways - drop the third code to your app, according to success or error of the asynchronous call, the function returns `true` or `false`. So this code is totally fine. The problem is rather with your other code which uses that true/false response from this call. That's why I've said at the beginning that plunker would be very helpful. – kind user Jan 05 '17 at 20:56