Raghu Chaitanya
Raghu Chaitanya

Reputation: 151

Promise Chaining

Hi I am trying to implement Promise Chaining Using q-library in my angular project below are my 2 methods and the way they are chained.I have also posted method implementations to understand my problem. Now in pathUserDataFromAuthService method I would like to access the Etag value that i have set in the first Promise i.e getUserDataFromAuthServer using setEtag() method , The problem here is getEtag() method is called before the first promise data is resolved .

How would ensure that correct Etag value is coming up

Any help in this regard would be great

  getUserDataFromAuthServer(user)
            .then(pathUserDataFromAuthService(user))

and the method code is as below

    getUserDataFromAuthServer = function(user){
                    var defer=$q.defer();
                    $http.get(autherizationURL+'/'+'api/users/'+user.username)
                   .then(function(response){
                        var ETag =response.headers().etag;
                        console.log("etag"+ETag)
                        setEtag(ETag)
                        console.log("Etag Set changed");
                        defer.resolve(response.data);
                    },function(error){          
                          defer.reject(error.statusText);
                    });
                    return defer.promise;       
                };



            var pathUserDataFromAuthService = function (user){      
                var defer=$q.defer();
                var passwordtobesaved ={
                        "firstName": user.firstName,
                        "lastName": user.lastName
                    };
                var tag = getEtag();
            $http.put(autherizationURL+'/'+'api/users/'+user.username,passwordtobesaved,{
                    headers:{
                        "If-Match": tag
                    }
                }).then(function(response){

                    defer.resolve(response.data);
                },function(error){          
                      defer.reject(error.statusText);
                });
                return defer.promise;       
            };

Upvotes: 0

Views: 241

Answers (2)

Roamer-1888
Roamer-1888

Reputation: 19288

As already pointed out, the main issue is that then() accepts function(s).

After that, the need to pass user makes things slightly awkward but nothing that javascript can't cope with.

A number of approaches are possible. Here are two.

1. Pass user and etag separately, with the help of .bind()

It's maybe not obvious how this works because the two parameters user and etag are passed by different mechanisms :

  • user: is "bound"
  • etag: is delivered by the promise chain to the function returned by .bind()
getUserDataFromAuthServer(user).then(pathUserDataFromAuthService.bind(null, user));

getUserDataFromAuthServer = function(user) {
    return $http.get(autherizationURL + '/api/users/' + user.username).then(function(response) {
        return response.headers().etag;
    });
};

var pathUserDataFromAuthService = function(user, etag) {
    return $http.put(autherizationURL + '/api/users/' + user.username, {
        "firstName": user.firstName,
        "lastName": user.lastName
    }, {
        headers: { "If-Match": etag }
    }).then(function(response) {
        return response.data;
    });
};

2. Deliver user and etag as properties of a single object

This is probably more intuitive. The promise chain delivers a single object to pathUserDataFromAuthService as data.

getUserDataFromAuthServer(user).then(pathUserDataFromAuthService);

getUserDataFromAuthServer = function(user) {
    return $http.get(autherizationURL + '/api/users/' + user.username).then(function(response) {
        return {
            user: user,
            etag: response.headers().etag
        };
    });
};

var pathUserDataFromAuthService = function(data) {
    return $http.put(autherizationURL + '/api/users/' + data.user.username, {
        "firstName": data.user.firstName,
        "lastName": data.user.lastName
    }, {
        headers: { "If-Match": data.etag }
    }).then(function(response) {
        return response.data;
    });
};

In both solutions setEtag() / getEtag() disappear on the assumption that they existed (in the question) solely as a mechanism for passing ETag. If necessary for other reasons (eg side-effects), they can be reintroduced without consequence (unless they throw).

Upvotes: 0

Asaf David
Asaf David

Reputation: 3297

No need to use defer, this is an anti-pattern. You can simply pass on the promise by returning the http request.

Here's how it should be:

getUserDataFromAuthServer = function(user){
  return $http.get(autherizationURL+'/'+'api/users/'+user.username)
      .then(function(response){
           var ETag =response.headers().etag;
           console.log("etag"+ETag)
           setEtag(ETag)
           console.log("Etag Set changed");
           return response.data;
        }
};

Same thing can be done in your second function, although I don't see why it's needed since you do nothing when it ends.

var pathUserDataFromAuthService = function (user){      
  var passwordtobesaved ={
    "firstName": user.firstName,
    "lastName": user.lastName
  };
  var tag = getEtag();
  return $http.put(
    autherizationURL + '/' + 'api/users/' + user.username, 
    passwordtobesaved, 
    { headers: { "If-Match": tag } }
  )
};

Upvotes: 1

Related Questions