lycosis
lycosis

Reputation: 151

Sync Service's Async-Response to Controller Variable

I am having a hard time using promises and passing information between a service and controller.

The code below functions, in that it makes the calls, I get the promises back, I perform work on them, etc. I want to pass status messages back to the controller now, but I can't figure out to return them to the controller.

How can I sync myService's non-promise response with my controller variable? Or should I just be returning the $q.all promise back to the controller and then having the controller call the statusService?

Ideally, I want the controller to just "fire and forget" and wait for a status response so I can update a modal.

Controller

function doWork() {
  myService.doSomeWork();

  // what I'm going for:
  // var statusMessage = myService.doSomeWork(sharedDataService.onThisThing);
}

Service

factory.doSomeWork = function() {        
  var promises = [
    queryApi("firstApiCall"), 
    queryApi("secondApiCall")
  ];

  $q.all(promises)
    .then(function(res) {
      workService.doSomething(res[0].data, res[1].data);
      console.log("response:", res);
      // I want to return a string, or object, back to a variable in my controller
      //return statusService.getStatusMessage(res[0]);
    }, function(err) {
      console.log("error:", err);
      //return statusService.getStatusMessage(err);
    }
  );      
};

function queryApi(url) {
  return $http.get(url);
}

Any help would be appreciated.

Upvotes: 0

Views: 70

Answers (2)

georgeawg
georgeawg

Reputation: 48968

In AngularJS, asynchronous services should return a promise. To transform promise data in a service, be sure to return the transformed data to the .then method handler function:

factory.doSomeWork = function() {        
  var promises = [
    queryApi("firstApiCall"), 
    queryApi("secondApiCall")
  ];

   ̲r̲e̲t̲u̲r̲n̲ $q.all(promises)
    .then(function successHandler(res) {
      workService.doSomething(res[0].data, res[1].data);
      console.log("response:", res);
      // I want to return a string, or object, back to a variable in my controller
       ̲r̲e̲t̲u̲r̲n̲ transformedData;
    }, function rejectionHandler(err) {
      console.log("error:", err);
       ̶/̶/̶r̶e̶t̶u̶r̶n̶ ̶s̶t̶a̶t̶u̶s̶S̶e̶r̶v̶i̶c̶e̶.̶g̶e̶t̶S̶t̶a̶t̶u̶s̶M̶e̶s̶s̶a̶g̶e̶(̶e̶r̶r̶)̶;̶
       ̲t̲h̲r̲o̲w̲ statusService.getStatusMessage(err);
    }
  );      
};

It is important to use a throw statement in rejection handlers. Otherwise the rejected promise will be converted to a successful promise.

In the controller:

function doWork() {
  var promise = myService.doSomeWork();

  promise.then(function(transformedData) {
      console.log(transformedData);
  }).catch(function(err) {
      console.log(err);
  });

  // what I'm going for:
  // var statusMessage = myService.doSomeWork(sharedDataService.onThisThing);
}

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

Upvotes: 1

Padmanabha Vn
Padmanabha Vn

Reputation: 624

You can do a callback from the service like

  factory.doSomeWork = function(callback) {        
 var promises = [
   queryApi("firstApiCall"), 
   queryApi("secondApiCall")
];

 $q.all(promises)
   .then(function(res) {
  //do a callback

  callback(res)

   }, function(err) {
       console.log("error:", err);

   }
  );      
};

and in your controller you can receive the result

  function doWork() {
  myService.doSomeWork(function(result){
 //handle the result
});

}

Upvotes: 0

Related Questions