dilluns, 6 de febrer del 2017

AngularJS, $q and promises


First, to say that these entries in the blog only are a way to learn. I'm learning english for my self and I think that this is a good way to practice, so there if are some phrase poorly constructed I apologize for it.
Continuing with the asynchronous task, this time seeing as AngularJS treat the problem.
AngularJS is a javascript open source framework maintained by Google commonly used for develop single-page application. You can find more info about this technology here.

In the previous entry I commented that javascript don't use threads and who the browser only uses a thread for each page and if a task spends a lot of time it can block the browser. For solve that and not fall into callback hell, AngularJS uses the concept of promises based on Kris Kowal's Q proposal. You can find more info here.

Essentially a promise is a javascript object who in a future it will contain the value we want to return but in this moment we don't know. Each asynchronous task will return a promise and each promise have a then function with two arguments, a success handler and an error handler. The success or the error handler will be called only one time when the asynchronous task is finished. The success and error handler can return a value which will be passed to the next function in the chain of promises if exist. The then function returns a promise to allow chaining multiple calls.

A prototype can be


   method().then(function(data){
      //Manage data 
   }, function(error) {
      //Manage error
   });

And can be to chained multiple calls

   method().then(Success1, Error1)
           .then(Success2, Error2)
           .then(Success3, Error3);

For this example we are going to make a query to the wikipedia and extract a bit of info. For this, we will use the mediawiki API. You can find more info here.

For good practices, we will use the $q service from de AngularJS core and although we could use it in the controller, by good practices we will separate it creating a service.


The service it would be like this


service('fetchDataService', ['$http', '$q',function($http, $q){
   return {
      getData: function (textToSearch) {
                            
         var deferred = $q.defer();                   

         var lang = navigator.language || navigator.userLanguage;

         var wikiURL = ".wikipedia.org/w/api.php";
         var url = "https://" + lang + wikiURL + "?action=opensearch&search=" 
                       + textToSearch + "&limit=10&explaintext&format=json";
                                                 
         var result = "";

         $http.get(url).then(
            function(response) {
               result = JSON.stringify(response.data[2]);
                                    
               result = result.substring(2, result.length - 2);
               deferred.resolve(result);

             }, function(errResponse) {
                deferred.reject(errResponse.data);
             });

             return deferred.promise;                        
          }
       }                    
    }])


We first created the deferred object using the AngularJS $q object to make promises. This object will be used inside of the asynchronous call and it have two methods, resolve that we use in the success handler to which we pass the data obtained in the http get call. The second method reject is used for indicate who the request is rejected and we pass it the error as a parameter. Finally returns the promise whit the data.

Now we inject the service in the controller and use it.



controller('MainCtrl', ['fetchDataService', function(fetchDataService) {
   var self = this;
   self.text = "";
                    
   self.search = function() {
      fetchDataService.getData(self.textToSearch)
         .then(function(data) {
            self.text = data;
         }).catch(function(error) {
            self.text = error;
         });
   }
}]); 

Cap comentari:

Publica un comentari a l'entrada