Roaders Roaders - 1 year ago 85
AngularJS Question

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.

Answer Source

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.