1

I am trying to send a request in AngularJS to get a token for user registration. Once I get the token, I am sending another request using the token to register the user.

However the first request works and I get the token, but the second one does not work.

Code

facebookExample.controller('registerController', function($scope, $http, $localStorage, $location) {
  $scope.data = {};
  $scope.getToken = function() {
      $http.post('http://you-serve.org/api.php?action=createaccount&format=json&name=' + $scope.data.username + '&email=' + $scope.data.email + '&realname=' +
        $scope.data.firstname + ' ' + $scope.data.lastname +
        '&mailpassword=false&reason=Fun_and_profit&language=en&token').then(
        function(response) {
          return response.data.createaccount.token;
        }
        // End success
        ,
        function() {
          alert('error');
        } // End error 
      ); //End then
    } // End getToken

  $scope.register = function(myToken) {
      $http.post('http://you-serve.org/api.php?    action=createaccount&format=json&name=' +
        $scope.data.username + '&email=' +
        $scope.data.email + '&realname=' +
        $scope.data.firstname + ' ' +
        $scope.data.lastname +
        '&mailpassword=false&reason=Fun_and_profit&language=en&token=' + myToken).then(
        function(response) {
          alert("Registration successful !  You can log in now " + response.data.createaccount.username);
        },
        function(response) {
          alert(response.data.error.info);
        }); //End then
    } //End register


  $scope.signup = function() {
      register(getToken);
    } // End sign up
}); // End controller
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.10/angular.min.js"></script>
<ion-view ng-controller="registerController" title="Sign Up" view-title="Sign Up" name="login-view">

  <ion-content class="padding">
    <div class="list list-inset">
      <label class="item item-input">
        <input type="text" placeholder="Username" ng-model="data.username">
      </label>
      <label class="item item-input">
        <input type="password" placeholder="Password" ng-model="data.password">
      </label>


      <label class="item item-input">
        <input type="text" placeholder="Email" ng-model="data.email">
      </label>


      <label class="item item-input">
        <input type="text" placeholder="First Name" ng-model="data.firstname">
      </label>

      <label class="item item-input">
        <input type="text" placeholder="Last Name" ng-model="data.lastname">
      </label>



      <label class="item item-input">
        <input type="text" placeholder="City" ng-model="data.city">
      </label>




      <label class="item item-input">
        <input type="text" placeholder="Country" ng-model="data.country">
      </label>
    </div>
    <button class="button button-block button-calm" ng-click="register(getToken())">Sign Up</button>
  </ion-content>
</ion-view>

Anyone know how I can I do this ?

2
  • You can create a local variable, assign the token to the local variable. And then pass it to second http request. Commented Dec 13, 2015 at 15:08
  • Since $http call is async, you will have to call second request inside success of first. Commented Dec 13, 2015 at 15:11

2 Answers 2

7

You can chain promises (which is what $http returns) by using promise1.then(promise2).

So in your case the correct way to chain getToken and register is:

$scope.getToken().then($scope.register)

(after you modify the two functions to return the $http calls)

Edit: (further explanation)

What you are trying to do is called promise chaining. Esentially, executing two or more asynchronous operations in sequential order. From the html5rocks promise tutorial:

Queuing asynchronous actions

You can also chain "then"s to run async actions in sequence.

When you return something from a "then" callback, it's a bit magic. If you return a value, the next "then" is called with that value. However, if you return something promise-like, the next "then" waits on it, and is only called when that promise settles (succeeds/fails).

The way this works is that when you return a value from the Promise or the .then() function, then the next then function in the chain is called with the return value of the .then() function or the resolution of the Promise, and if the return value is a Promise, the chain then waits on this Promise to resolve before it continues.

Thus (and remember than $http returns a Promise object):

function a() {
    return $http.get('...').then(function (response) { return response.data; });
}

function b(data) {
    return $http.get('...'+data).then(function (response) { return response.data; });
}

To chain the two functions together, so that b() gets called with the result of a(), just do this:

a().then(b)

Do read the tutorial on Promises to get a better handle on how they work. They are one of the best tools JavaScript has to make asynchronous operations easier to handle.

PS: In your specific case, the code would be:

facebookExample.controller('registerController', function($scope, $http, $localStorage, $location) {
  $scope.data = {};

  function getToken() {
    return $http.post('http://you-serve.org/api.php?action=createaccount&format=json&name=' + $scope.data.username + '&email=' + $scope.data.email + '&realname=' + $scope.data.firstname + ' ' + $scope.data.lastname + '&mailpassword=false&reason=Fun_and_profit&language=en&token')
      .then(
        function(response) {
          return response.data.createaccount.token;
        },
        // End success
        function() {
          alert('error');
        } // End error 
      ); //End then
  } // End getToken

  function register(myToken) {
    return $http.post('http://you-serve.org/api.php?action=createaccount&format=json&name=' +
        $scope.data.username + '&email=' +
        $scope.data.email + '&realname=' +
        $scope.data.firstname + ' ' +
        $scope.data.lastname +
        '&mailpassword=false&reason=Fun_and_profit&language=en&token=' + myToken)
      .then(
        function(response) {
          alert("Registration successful !  You can log in now " + response.data.createaccount.username);
        },
        function(response) {
          alert(response.data.error.info);
        }
      ); //End then
  } //End register


  $scope.signup = function() {
    getToken().then(register);
  } // End sign up
}); // End controller
Sign up to request clarification or add additional context in comments.

3 Comments

To return the $http calls ? Example ?
I think @souldreamer means that getToken() should return an object (or other value) that is usable by register()
Thanks @souldreamer !
2

you can do it in two ways :

Method 1 - Normal Way:

$scope.getToken = function() { 
    $http.post().then(function success(response) {
         // call register method here
         $scope.register(response.data.createaccount.token);
    }, function error(reason) {
      // do something
    });
};

Method 2 - Use $watch:

$scope.token = null;

 $scope.getToken = function() { 
        $http.post().then(function success(response) {
             // set the token value here
             $scope.token = response.data.createaccount.token;
        }, function error(reason) {
          // do something
        });
    };

$scope.$watch(function () { return $scope.token;}, 
function (newVal, oldVal) { 

if (newVal !== oldVal) {
   $scope.register(newVal);
}

});

1 Comment

Rabi, thanks for your response. I have done method 1 before. It s the closest to working I got . However still the user is not registered in the database. I m starting to think my error has to do with something other than the requests.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.