Importance of Promise Object in angular js

Hey guys, Writing this blog just to share an experience with you all. We have an input box which accepts keyword from user. We are sending api call to search that keyword, not when user enters full keyword, but when user enters a single character. And then it displays those keywords in drop-down.

We are using ngTagsInput plugin to add or select keyword. We send first api call when user enters first three characters and other calls are sent for each character entered by user. Due to this one issue occurs. Api responses are not received at same speed at which the user is entering the characters. So old response were displayed in the drop-down instead of new ones.

Ex. -> user entered ‘abcdef’, so, we have response for the api call which is given for ‘abcd’, but response for ‘abcde’ and ‘abcdef’ are pending. What we expect, is that it should display results of ‘abcdef’ in drop-down but it displays result of ‘abcd’. To resolve this issue we used promise object as shown below:

Solution

We used promise’s states like pending, fulfilled and rejected. We are rejecting those promises which have pending api calls. Let me explain with some code snippets.

Ex.

Api call:


def all_keywords
  word = params[:word]
  keywords = User.where(keywords: /#{word}/).pluck(:name).flatten
  render json: {keywords: keywords}
end

HTML

<tags-input ng-model="keywords" replace-spaces-with-dashes="false" class="tag-group" placeholder="Type keywords here">
  <auto-complete source="load_keywords($query)" select-first-match=="false" min-length="2" highlight-matched-text="true"

  </auto-complete>
</tags-input>

In JS Controller


$scope.load_keywords = function(word){
  if(word.length >= 2){
    if($scope.promise_object){
      $scope.promise_object.reject;
    }

    // Api call to get keywords
    $scope.promise_object = User.all_keywords({word: word}).$promise
    return $scope.promise_object.then(function(response){
      return response.keywords;
    });
  } else {
    return [];
  }
}

Brief introduction to promise object:

The Promise object is like ‘Santa’ gift to asynchronous programming languages. What is asynchronous? Ex. Javascript, Our code may or may not run in the sequence we have written.

To understand importance of promise object, you have to first understand what is a Callback. Callback comes in picture when we have to handle asynchronous calls in synchronous way.

Ex. of callback:


$.get(first_api_call, function(first_response){
  $.get(second_api_call, function(second_response){
    $.get(third_api_call, function(third_response){
      // Handle every response here
      if(first_response) {
        if(second_response) {
          if(third_response) {
            console.log(first_response, second_response, third_response);
          }
        }
      }
    })
  })
 })
})

It solves the problem of async calls, but it seems very difficult to understand and debug. What if there are three more api calls that are to be added in inner if? This will become a Callback Hell!!

To overcome this problem promise comes in existence. Whether api’s response is success or failure, promise tells you how to deal with it. Promise gives you result either now or in future.

In angular js $q service provides the functionality of promise. Promise provide us states like(pending, fulfilled, rejected). And also provides some methods like resolve(), reject() all(), race().

Simple Ex. of promise:


function test(){
 var deffered = $q.deffer();
   // deffer gives us a promise object
   var promise_object1 = deffered.promise;
   promise_objetc1.then(function(success_response){
     console.log(success_response);
   }, function(error_response){
     console.log(error_response);
   });
   deffered.resolve("It gives success response..!");
}

In above example first argument handles success response.

If we reject the promise due to some reason, it will execute second argument. That is instead of resolve we can reject it as shown below:

 
deffered.reject("It gives error response..!");

You can use callbacks too and put if conditions, but then the code would become to complex to understand and maintain. So an easier way is to use promise.

Ex. with multiple api calls:


function first_promise(val){
  deffered.resolve(val)
  return deffered.promise
}

var first_obj = first_promise(10);

function second_promise(val){
 deffered.resolve(val);
 return deffered.promise;
}

var second_obj = second_promise(20);

$q.all([first_promise, second_promise])
.then(function(response){
   // All are resolved
   console.log("first_result: " + response[0], "second_result: " + response[1]);
})

In above example we are using all() which returns the array of results of provided promise objects. And it goes in .then function only if all promises are resolved.

Promise Chaining:


User.get({id: u_id})
 .then(Business.get(u_id: user_response.id))
 .then(Location.get(b_id: business_resposne.id))
 .then(function(response){
   console.log("Location response: " + response);
})
.catch(function(response){
   console.log("Error response: " + response);
})

In above example, we want to get location only if user and business gives success response for .get api call. So we can handle this using promise chaining. It can be used to handle Callback Hell.

NOTE: In addition to promise you can also use angular js debounce to delay the API calls. Thus optimizing the requests sent to the server.

Advertisements

One thought on “Importance of Promise Object in angular js”

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s