During the course of my project, I have encountered a perplexing situation that is difficult to comprehend. My intuition tells me that the issue lies in a peculiar nuance of javascript while I am working in TypeScript. Unfortunately, I am unable to prove this theory or find a solution.
Background
In the application I am developing, there is a standard service responsible for interacting with a Web API.
The unusual aspect is that instead of using TypeScript's 'lambda' syntax for a $http.get(...).then(...)
success callback, I have opted for class functions. The reason being that the existing code utilizes the error callback and the usage of
$http.get(...).then(success, error)
with lambda syntax can be cumbersome to read.
// Not the most elegant, but works.
this.$http.get(...).then(() => { ... });
// Yikes...
this.$http.get(...)
.then(() => {
...
}, () => {
...
});
// Much cleaner!
this.$http.get(...)
.then(onFooSuccess, onError);
Below is the relevant service:
namespace MyApp.Models {
export class WebApiResult<T> {
public data: T;
}
}
namespace MyApp.Services {
export class SomeService {
public status: SomeServiceStatus = new SomeServiceStatus();
public static $inject: string[] = ['$http'];
public constructor(
public $http: ng.IHttpService
) {
}
public doSomething(): ng.IPromise<SomeServiceStatus> {
this.$http.get('/api/some/SomeAction')
.then(this.onDoSomethingSuccess, this.describeError);
}
// This method poses a problem. There seems to be a type error when executed.
public onDoSomethingSuccess(result: Models.WebApiResult<SomeServiceStatus>): SomeServiceStatus | ng.IPromise<SomeServiceStatus> {
if(!result.data.isInSpecialState) {
return result.data;
}
// TypeError! Unable to assign value to undefined.
this.status = result.data;
return result.data;
}
public describeError(error: any) {
alert('oops');
}
}
export class SomeServiceStatus {
public isInSpecialState: boolean = false;
public someStatusMessage: string = '';
public someIdentifier: string = '';
}
angular
.module('app')
.service('someService', SomeService);
}
Problem
Although the $http
get request is successful, the issue arises within the success callback. Each time the line this.status = result.data
is executed, an exception occurs due to the inability to assign result.data
to the status
property of undefined
.
My current assumption is that this
does not reference the SomeService
as intended, but rather something else, possibly even the class method used as the delegate.
Questions
This speculation raises several inquiries.
- What does
this
exactly refer to? Hovering over it in Visual Studio 2015 displays the cryptic information:this: this
. Thanks Microsoft. - Is it expected behavior for
this
to function this way? Is this a TypeScript bug or simply a mistake in the generated JavaScript? - Are there preferred stylistic approaches when handling an AngularJS promise with both success and error callbacks? Perhaps there is a more efficient way to write the code that I am overlooking or lacking knowledge about. Asking questions on SO has often led to valuable insights.