7

I wonder how to simulate a promise $http when I know that the request will fail on the server-side. Here is my code:

if ( !ng.isString(email) ) {
    var promise = $q.defer().promise;
    $q.reject();

    return promise;
}

return $http( {
         method : "PUT",
         url : "//localhost/update" ,
         data : { data: email } 
})

// Success handler
.success(response){ return response})

// Error handler
.error(errorMsg){ return errorMsg});
Frank6
  • 1,193
  • 1
  • 11
  • 23

6 Answers6

5

You can use resolve and reject to control the flow of your data:

Let's say you have a service like this:

var app = angular.module("mymodule.services", []);

app.factory("HttpRequest", ['$q', '$http', function(q, http) {
  var deferredData = q.defer();

  http.get('http://your-server.local/data.json').success(function(data) {
    //success, resolve your promise here
    deferredData.resolve(data);
  }).error(function(err) {
    //error, use reject here
    deferredData.reject(err);
  });

  return {
    get: function() {
      return deferredData.promise;
    }
  };
}]);

The service can then be used as such:

var app = angular.module("mymodule.controllers", ['mymodule.services']);

app.controller("MyCtrl", ['HttpRequest', '$scope', function(res, scope) {
  //the "then"-method of promises takes two functions as arguments, a success and an erro callback
  res.get().then(function(data) {
    //first one is the success callback
    scope.data = data;
  },
  function(err) {
    scope.err = err; 
  }); 
}]);

You can handle the error in the second callback.

Florian
  • 3,366
  • 1
  • 29
  • 35
  • Thanks for your answer! Sounds good but I need to be able to use the `success` and `error` method instead of `then` – Frank6 Aug 15 '13 at 13:33
  • The promises that `$q` offers in angular don't have those methods out of the box, i suggested modifying them here: http://stackoverflow.com/questions/17686612/rejecting-promises-with-multiple-arguments-like-http-in-angularjs/17687321#17687321 – Florian Aug 15 '13 at 18:09
5

Ok, I could figure out how to simulate the same promise returned by the $http object. Thanks to all for your answers. I could take them all into consideration. Here is my solution :

if ( !ng.isString(email) ) {

    // We need to create a promise like the one returned by the 
    // $http object (with the success and error methods)
    // to stay consistent.
    var promise = $q.reject("error with email");

    // Defining success and error method for callbacks. 
    // but it should never be called since the promise 
    // is already rejected.
    promise.success = function(fn){
       promise.then(function(response){
          fn(response)
       }, null);
          return promise
    };

    promise.error = function(fn){
       promise.then(null, function(response){
          fn(response)
       });
       return promise;
    };

    return promise;
}

return $http( {
         method : "PUT",
         url : "//localhost/update" ,
         data : { data: email } 
})

// Success handler
.success(response){ return response})

// Error handler
.error(errorMsg){ return errorMsg});
Frank6
  • 1,193
  • 1
  • 11
  • 23
  • 1
    I am wondering why the `success` and `error`methods are not already defined in a promise. It seems like it would be useful don't you guys think ? – Frank6 Aug 15 '13 at 14:26
  • 1
    I needed to do something like this. My solution is similar, but thought I'd point out that `promise.then(function(response){ fn(response); })` is effectively the same as `promise.then(fn)`. – Jacob Ensor Jun 04 '15 at 18:27
3

The $http return a promise in angularJS. You can do like this :

var promise = $http(...) ;
promise.then(function(data) {}, function(error){});

You may look for the success and error functions in jQuery ajax call but it's different thing that works here in angularJS. You may need to follow it to make it work properly.

You can tell us more about the reason why do you need to use success and error so we can find a way to make it work with your case.

Dzung Nguyen
  • 9,152
  • 14
  • 65
  • 104
1

Something like this should work:

if ( !ng.isString(email) ) 
    return $q.reject("Email is invalid.");  // returns rejected promise

return $http( {
         method : "PUT",
         url : "//localhost/update" ,
         data : { data: email } 
});

then in your code use it as a regular promise

mypromise.then(function(x) { do something with x.data }, function(error) { alert(error)});
Karen Zilles
  • 7,633
  • 3
  • 34
  • 33
  • Thanks for your answer! Sounds good too but I need to be able to use the `success` and `error` method instead of `then`... – Frank6 Aug 15 '13 at 13:38
1

Playing with your suggestion below (and debugging Angularjs code), I found a more simplified way which allows to reject or resolve.

if (alreadyLoaded){
    var defered = $q.defer();
    defered.success = function(fn){
        defered.promise.then(fn);
        return defered;
    };
    defered.error = function(fn){
        defered.promise.then(null, fn);//or defered.promise.catch(fn)
        return defered;
    };
    if(data.invalid)
        defered.reject("arbitrary error");
    else
        defered.resolve(data);
    return defered;
}else {
    return $http.get(...);
}

(both success and error methods return this to allow enqueued callbacks)

Ivan Ferrer Villa
  • 2,129
  • 1
  • 26
  • 23
0

Your syntax is a little messed up. Try this instead:

var deferred = $q.defer();
$q.reject();
return deferred.promise;
Mike Robinson
  • 24,971
  • 8
  • 61
  • 83
  • Thanks for your answer! But because of I need to be able to use the `success` and `error` method instead of `then`, I get the following error : Object # has no method 'success' – Frank6 Aug 15 '13 at 13:37
  • Fighting the different promise interfaces between HttpPromise and Promise – Jason Jarrett Sep 15 '13 at 06:22