Roaders
Roaders

Reputation: 4525

Using 'this' in $http callback with AngularJS and Typescript

I am using a promise in a service and then when the result loads I want to navigate to another page.

My Code:

export class PicasaAuthenticator
{
    //  Constructor

    static $inject = [ '$window', '$location', '$http' ];
    constructor( private window : ng.IWindowService, private location : ng.ILocationService, private http : ng.IHttpService )
    {
    }

    //  Private Functions

    private validateToken( results : IAuthResults ) : void
    {
        if( results && results.access_token )
        {
            var validateTokenURL : string = "https://www.googleapis.com/oauth2/v1/tokeninfo";
            validateTokenURL += "?access_token=" + results.access_token;

            this.http.get<ITokenValidationResult>( validateTokenURL );
            this._validationPromise.then( this.handleTokenVerificationResult,this.handleTokenVerificationError );
        }
    }

    private handleTokenVerificationResult( successResponse : ng.IHttpPromiseCallbackArg<ITokenValidationResult> ) : void
    {
        this._validationPromise = null;

        if( successResponse.data.audience = client_id )
        {
            this.location.path( '/albums' );
        }
        else
        {
            alert( "audience does not match client ID" );
        }
    }
}

The problem is that this.location of course doesn't exist in the handleTokenVerificationResult. How do I set the scope that this function should run under? I saw an example using var self = this (which I don't like anyway) but this didn't work.

Thanks for any help.

Upvotes: 1

Views: 419

Answers (1)

GregL
GregL

Reputation: 38121

It may not be as pretty, but using the arrow function notation will preserve the this value correctly, so I would try changing your validateToken() function to the following:

private validateToken( results : IAuthResults ) : void
{
    if( results && results.access_token )
    {
        var validateTokenURL : string = "https://www.googleapis.com/oauth2/v1/tokeninfo";
        validateTokenURL += "?access_token=" + results.access_token;

        this.http.get<ITokenValidationResult>( validateTokenURL );
        this._validationPromise.then( () => {
            this.handleTokenVerificationResult.apply(this, arguments); 
        }, () => { 
            this.handleTokenVerificationError.apply(this, arguments); 
        });
    }
}

Alternatively, just use Function.bind() to preserve the value of the this variable:

private validateToken( results : IAuthResults ) : void
{
    if( results && results.access_token )
    {
        var validateTokenURL : string = "https://www.googleapis.com/oauth2/v1/tokeninfo";
        validateTokenURL += "?access_token=" + results.access_token;

        this.http.get<ITokenValidationResult>( validateTokenURL );
        this._validationPromise.then(this.handleTokenVerificationResult.bind(this), this.handleTokenVerificationError.bind(this));
    }
}

However, you should note that using .bind() destroys type information in TypeScript, currently, so I mostly stick with using arrow functions to preserve the type information correctly.

Upvotes: 2

Related Questions