Recently I was working with Azure and handling the asynchronous request callback using an Angular promise. This presented me with a couple of difficulties:
- When calling .resolve on the deferral, it was never firing the .when statement on the code that was holding the promise so I never got may data loaded correctly from my factory
- Inside the deferral callback code in a class, any calls to the classes properties using the 'this' operator were failing with an undefined or null reference error
Calling code:
this.dataAccess.BeginGetRegistrations().then(function (result: Classes.RegistrationDTO[]) {
for (var i in result) {
var registrationDTO: Classes.RegistrationDTO = result[i];
var registration: Registration = new Registration(registrationDTO.Id, this.dataAccess);
registration.LoadRegistration(registrationDTO.ScreenName, registrationDTO.Email, registrationDTO.Zip, registrationDTO.Gender, registrationDTO.BirthDate);
this.Add(registration);
}
});
Asynchronous function in my data access class:
public BeginGetRegistrations(): ng.IPromise<Classes.RegistrationDTO[]>{
var deferral = this.service.defer<Classes.RegistrationDTO[]>();
var registrations = DataAccess.client.getTable('Registration');
registrations.read().done(function (results) {
var returnValue: Classes.RegistrationDTO[] = [];
var registration: Classes.RegistrationDTO;
for (var i in results) {
var result = results[i];
registration = current.LoadResult(result);
returnValue.push(registration);
}
deferral.resolve(returnValue);
}, function(err) {
throw err.toString();
});
return deferral.promise;;
}
I did a little digging around it seemed obvious. The call to resolve on the deferral needs to happen in a context that Angular is aware of. In this case, calling resolve inside $apply method on the $rootScope should solve it so the .when statement on the calling code fires. Since I was way down in the bowls of a class inside a module I had Angular inject the $rootScope into my factory which in turn set it inside my data access class on creation (constructor). Now my data access class has a reference to the $rootScope in a class level variable called scope.
I rewrote my code hoping to get the .when to fire like this:
public BeginGetRegistrations(): ng.IPromise<Classes.RegistrationDTO[]>{
var deferral = this.service.defer<Classes.RegistrationDTO[]>();
var registrations = DataAccess.client.getTable('Registration');
registrations.read().done(function (results) {
var returnValue: Classes.RegistrationDTO[] = [];
var registration: Classes.RegistrationDTO;
for (var i in results) {
var result = results[i];
registration = current.LoadResult(result);
returnValue.push(registration);
}
this.scope.$apply(deferral.resolve(returnValue));
}, function(err) {
throw err.toString();
});
return deferral.promise;;
}
As soon as I did this, the second problem raised its head. That is, I couldn't get access to the 'this' keyword and was failing with an undefined or null reference. This problem manifested in both the BeginGetRegistration method and the calling code. The solution was simple. In each of these methods set a local variable equal to the class level 'this' variable so the callback function has access to it and all was well with the world. My new corrected and working functions:
Calling code:
var current: any = this;
this.dataAccess.BeginGetRegistrations().then(function (result: Classes.RegistrationDTO[]) {
for (var i in result) {
var registrationDTO = result[i];
var registration: Registration = new Registration(registrationDTO.Id, current.dataAccess);
registration.LoadRegistration(registrationDTO.ScreenName, registrationDTO.Email, registrationDTO.Zip, registrationDTO.Gender, registrationDTO.BirthDate);
current.Add(registration);
}
});
Asynchronous function in my data access class:
public BeginGetRegistrations(): ng.IPromise<Classes.RegistrationDTO[]>{
var deferral = this.service.defer<Classes.RegistrationDTO[]>();
var registrations = DataAccess.client.getTable('Registration');
var current: any = this;
registrations.read().done(function (results) {
var returnValue: Classes.RegistrationDTO[] = [];
var registration: Classes.RegistrationDTO;
for (var i in results) {
var result = results[i];
registration = current.LoadResult(result);
returnValue.push(registration);
}
current.scope.$apply(deferral.resolve(returnValue));
}, function(err) {
throw err.toString();
});
return deferral.promise;;
}
With these fixes in place my Azure mobile code was loading beautifully, asynchronously and Angular binding was handling the data coming back and displaying on the UI exactly as it should.
Thank you for benefiting from time to focus on this kind of, I feel firmly about it and also really like comprehending far more with this particular subject matter. In case doable, when you get know-how, is it possible to thoughts modernizing your site together with far more details? It’s extremely useful to me
ReplyDeletepython Course in Pune
python Course institute in Chennai
python Training institute in Bangalore
Attend The Python training in bangalore From ExcelR. Practical Python training in bangalore Sessions With Assured Placement Support From Experienced Faculty. ExcelR Offers The Python training in bangalore.
ReplyDeletepython training in bangalore
Thank you for sharing .The data that you provided in the blog is informative and effective.
ReplyDeleteweb designing training in bangalore
web designing courses in bangalore
web designing classes in bangalore
web designing training institute in bangalore
web designing course syllabus
best web designing training
web designing training centers