最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

Javascript promise .catch not working - Stack Overflow

programmeradmin9浏览0评论

EDIT: SEE THE ANSWER BELOW

I have a function:

dataFactory.getCurrentStepId(wf.identifier, ctx.identifier)
   .then(function (data) {
      console.log('then');
      $timeout(function () {
      $("#app-node-" + data.identifier)
           .parent().parent().css("border", "5px solid green");
      });
    })
    .catch(function () {
      console.log('error');
      alert('Error!')
      });

The getCurrentStepId has an exception, and I see the error printed on the console for the AJAX request it sends, but my alert and console.log don't fire in the catch.

Any ideas why? Here is the stuff it's calling:

app.factory('dataFactory', function ($http, $q) {
    var _baseUrl = webServiceContext;
    var _doGet = function (endpoint) {
        var deferred = $q.defer();
        $http.get(_baseUrl + '/' + endpoint).then(function (response) {
            deferred.resolve(response.data);
        });
        return deferred.promise;
    };

    var getCurrentStepId = function (wid, cid) {
        return _doGet('wf/step/' + wid + '/' + cid);
    };
})

Here is the answer

@Blunderfest almost got it right:

 $http.get(_baseUrl + '/' + endpoint).then(function (response) {
            deferred.resolve(response.data);
        }).catch(function(e){return deferred.reject(e);});

EDIT: SEE THE ANSWER BELOW

I have a function:

dataFactory.getCurrentStepId(wf.identifier, ctx.identifier)
   .then(function (data) {
      console.log('then');
      $timeout(function () {
      $("#app-node-" + data.identifier)
           .parent().parent().css("border", "5px solid green");
      });
    })
    .catch(function () {
      console.log('error');
      alert('Error!')
      });

The getCurrentStepId has an exception, and I see the error printed on the console for the AJAX request it sends, but my alert and console.log don't fire in the catch.

Any ideas why? Here is the stuff it's calling:

app.factory('dataFactory', function ($http, $q) {
    var _baseUrl = webServiceContext;
    var _doGet = function (endpoint) {
        var deferred = $q.defer();
        $http.get(_baseUrl + '/' + endpoint).then(function (response) {
            deferred.resolve(response.data);
        });
        return deferred.promise;
    };

    var getCurrentStepId = function (wid, cid) {
        return _doGet('wf/step/' + wid + '/' + cid);
    };
})

Here is the answer

@Blunderfest almost got it right:

 $http.get(_baseUrl + '/' + endpoint).then(function (response) {
            deferred.resolve(response.data);
        }).catch(function(e){return deferred.reject(e);});
Share Improve this question edited Jan 29, 2016 at 18:15 mikeb asked Jan 29, 2016 at 18:00 mikebmikeb 11.4k8 gold badges69 silver badges132 bronze badges 8
  • 1 If catch was called anywhere else in your promise chain, then your catch will not fire. – arjabbar Commented Jan 29, 2016 at 18:03
  • A quick CTRL-F for catch in the javascript files shows that as the only place I'm using it. It's a pretty simple bit of code. – mikeb Commented Jan 29, 2016 at 18:05
  • Does your then callback fire at all? – arjabbar Commented Jan 29, 2016 at 18:07
  • For a valid query, yes it does – mikeb Commented Jan 29, 2016 at 18:07
  • So the exception isn't being thrown in the $timeout callback right? – arjabbar Commented Jan 29, 2016 at 18:09
 |  Show 3 more ments

3 Answers 3

Reset to default 2

Make sure you return a rejected promise in your catch blocks. So this:

$http.get(_baseUrl + '/' + endpoint).then(function (response) {
        deferred.resolve(response.data);
    })

Should be this:

$http.get(_baseUrl + '/' + endpoint).then(function (response) {
        deferred.resolve(response.data);
    }).catch(function(e){
         return $q.reject(e);
    });

Actually, you can use $q.reject as a shorthand for rejecting a promise, so I think it's a correct answer :). You can also use return $q.when(response) as a shorthand for deferred, resolve and all that.

I remend reading: $q.defer: You're doing it wrong

Really, I would re-organize your code to follow a few best practices on promises, especially in angular. It's better to return the $http request itself (which is a promise):

app.factory('dataFactory', function ($http, $q) {
    var _baseUrl = webServiceContext;
    var _doGet = function (endpoint) {
        // Returns the promise wholesale.
        return $http.get(_baseUrl + '/' + endpoint).then(function (response) {
            return response.data;
        }).catch(function(e){
            // ensures the returned promise is rejected up the chain.
            return $q.reject(e);
        });
    };

    var getCurrentStepId = function (wid, cid) {
        return _doGet('wf/step/' + wid + '/' + cid);
    };
})

Angular Docs for $q methods:

reject(reason) – rejects the derived promise with the reason. This is equivalent to resolving it with a rejection constructed via $q.reject

The reason you need to do this is that if you do not catch errors and reject promises at lower levels, the promise chain up the line will not know the promise is rejected and treat it as a success.

I find this article has great explaination and example

  1. Inside the promise, the catch() method will catch the error caused by the throw statement and reject().

  2. If an error occurs and you don’t have the catch() method, the JavaScript engine issues a runtime error and stops the program.

try this instead

dataFactory.getCurrentStepId(wf.identifier, ctx.identifier)
   .then(function (data) {
      console.log('then');
      $timeout(function () {
      $("#app-node-" + data.identifier)
            .parent().parent().css("border", "5px solid green");
  }, function (err) {
     console.log(err);
     alert(err);
  });

remember then takes 2 parameters - a function if successful, a function if error occurred. You only provided success.

发布评论

评论列表(0)

  1. 暂无评论