-2

I create $http service and using $q.

Here is my $http service:

function dashboardService($http, $log, $q, config) {

    var service = {
        getClientId: getClientIDByLayout,
    };

    return service;

    function getClientIDByLayout(layoutId) {
        var deferred = $q.defer();
        return $http.get(config.baseUrl + "api/ClientLayoutMercator?layoutId=" + layoutId).then(function (result) {
            deferred.resolve(result.data);
        }, function (result) {
            deferred.reject(result);
        });

        return deferred.promise;
    }  
}

And here is how I call service above inside controller:

  dashboardService.getClientId(layoutId).then(function (data) {
      var t = data;//undifined
   });

But result I get in this row var t = data is undefined.

Any idea why I get undefined from the service?

Michael
  • 13,950
  • 57
  • 145
  • 288

2 Answers2

3

Basically you have two return statement inside your getClientIDByLayout function and both are returning promise itself. As I can see with your current implementation your're creating new promise & managing rejection / resolve manually. But the problem is the 1st return statement (return $http.get() is making other return statement(return deferred.promise) redundant. Hence 1st promise returned to subscription from controller. Eventually $http.get doesn't return anything so you get undefined in successCallback of then.

You can easily fix this issue by removing 1st return statement as shown below.

function getClientIDByLayout(layoutId) {
    var deferred = $q.defer();
    //removed `return` from below code.
    $http.get(config.baseUrl + "api/ClientLayoutMercator?layoutId=" + layoutId).then(function (result) {
        deferred.resolve(result.data);
    }, function (result) {
        deferred.reject(result);
    });
    //custom promise should get return 
    return deferred.promise;
}  

Ideally creating promise overhead considered as antipattern, rather you can utilize the promise returned by $http.get. Just return a data from its success callback to chain the promise.

Code

function getClientIDByLayout(layoutId) {
    ̶v̶a̶r̶ ̶d̶e̶f̶e̶r̶r̶e̶d̶ ̶=̶ ̶$̶q̶.̶d̶e̶f̶e̶r̶(̶)̶;̶
    return $http.get(config.baseUrl + "api/ClientLayoutMercator?layoutId=" + layoutId)
      .then(function (result) {
         //returning data from promise, it will provide it to subsequent `.then`
         return result.data;
      }, function (error) {
         ͟r͟e͟t͟u͟r͟n͟ $q.reject(error);
      }
    );
}  
georgeawg
  • 48,608
  • 13
  • 72
  • 95
Pankaj Parkar
  • 134,766
  • 23
  • 234
  • 299
1

Instead of using $q.defer, simply return or throw to the handler functions in the .then method:

function dashboardService($http, $log, ̶$̶q̶,̶ config) {

    var service = {
        getClientId: getClientIDByLayout,
    };

    return service;

    function getClientIDByLayout(layoutId) {
         ̶v̶a̶r̶ ̶d̶e̶f̶e̶r̶r̶e̶d̶ ̶=̶ ̶$̶q̶.̶d̶e̶f̶e̶r̶(̶)̶;̶
        return $http.get(config.baseUrl + "api/ClientLayoutMercator?layoutId=" + layoutId).then(function (result) {
            ̶d̶e̶f̶e̶r̶r̶e̶d̶.̶r̶e̶s̶o̶l̶v̶e̶(̶r̶e̶s̶u̶l̶t̶.̶d̶a̶t̶a̶)̶;̶ 
            return result.data;
        }, function (result) {
            ̶d̶e̶f̶e̶r̶r̶e̶d̶.̶r̶e̶j̶e̶c̶t̶(̶r̶e̶s̶u̶l̶t̶)̶;̶ 
            throw result;
        });

        ̶r̶e̶t̶u̶r̶n̶ ̶d̶e̶f̶e̶r̶r̶e̶d̶.̶p̶r̶o̶m̶i̶s̶e̶;̶
    }  
}

The .then method returns a new promise which is resolved or rejected via the return value of the successCallback or errorCallback (unless that value is a promise, in which case it is resolved with the value which is resolved in that promise using promise chaining).1

By erroneously returning a promise with a then method that contained functions that lacked return or throw statements the service was returning a promise that resolved as undefined.

For more information, see You're Missing the Point of Promises.

georgeawg
  • 48,608
  • 13
  • 72
  • 95