【问题标题】:angular then catch success error from services角度然后从服务中捕获成功错误
【发布时间】:2017-01-04 18:32:57
【问题描述】:

恐怕我已经掉进了递归承诺的兔子洞。

我有一个服务来处理我的 api。 (它有一个额外的承诺层,因此如果 api 脱机,我可以切换回本地 json。(不知道它有多么必要)-为了简单起见,我可能应该消除它)。 然后我在我的控制器中得到了承诺的异步调用。

只要我得到我期望的数据,这一切都很好,但它不能很好地处理错误。当我得到 400 和 500 时,它不会通过 toastr 向用户发送错误消息。

遗憾的是,这不是一个完全兼容的 RESTful api。我得到的 400 错误简直就是

{"Message":"No packages found"}

我真的不知道如何让它发挥应有的作用,并将成功/错误替换为 then/catch(根据 Angular 最佳实践)。

这是一个典型的服务调用:

var _getPackagesPage = function (options) {

    var pageSize = options.data.pageSize;
    var page = options.data.page -1;
    return $q (function(resolve, reject) {
        switch (dataSource) {
            case 'api'://staging - live api data
                return $http({
                    method: 'get',
                    url: serviceBase + 'api/Packages?pageSize=' + pageSize + '&page=' + page
                }).then(function(results) {
                    resolve(results);
                });
                break;

            default: // dev - local json

                $.getJSON('Content/data/Packages.json', function (json) {
                    var pageSize = options.data.pageSize;
                    var page = options.data.page;
                    var newjson = json.splice(page*pageSize,pageSize);
                    resolve(newjson);
                });
        }
    });
};

以及控制器中的典型调用:

options是交回我的数据网格(剑道)的数据对象)

    vm.getPackages = function(options) {
        return packagesService.getPackagesPage (options)
            .then(function(results) {
                options.success(results.data.Items);
            })
            .catch(function(error) {
                options.error(error);
                toastr.error(error.Message);
            });
    };

我该如何清理这个?

[ UPDATE ] 已尝试按照下面的答案 1 进行修复

服务:

    var _getOrdersPage = function (options) {

        var deff = $q.defer();
        var pageSize = options.data.pageSize;
        var page = options.data.page -1;
        return $http({
            method: 'get',
            url: serviceBase + 'api/Packages?pageSize=' + pageSize + '&page=' + page
        })
        .then(
            function(results) {
                deff.resolve(results);
            },
            function(ex){ 
                deff.reject(ex);
            });
        return deff.promise;
    };

控制器:

    vm.getOrders = function (options) {
        return ordersService.getOrdersPage (options)
            .then(function(results) {
                console.log("results!");
                console.log(results);
            })
            .catch(function(error) {
                console.log("error!");
                console.log(error);
            });
    };

结果:

GET http:///api/Packages?pageSize=20&page=0 400(错误请求)

结果!

未定义

【问题讨论】:

  • 清理什么?你能问一个简单的问题吗?
  • 我希望可以。必须有一种正确 的方式来使用服务并进行 $http 调用并返回结果/错误。不是这个。
  • 您可以使用$http 加载json。只是说...
  • 是的,避免deferred antipattern
  • 我希望我能很好地理解 Promise 以识别 模式,更不用说 anti 模式了,更不用说将它分成两个模块了。

标签: angularjs promise


【解决方案1】:

为简洁起见,我将移除开关盒。

var _getPackagesPage = function (options) {

var pageSize = options.data.pageSize;
var page = options.data.page -1;
var deff = $q.defer();

$http({
      method: 'get',
      url: serviceBase + 'api/Packages?pageSize=' + pageSize + '&page=' + page
      }).then(
           function(results) {
              deff.resolve(results);
            },
            function(ex){ 
              deff.reject(ex);
             });

 return deff.promise;
    };

控制器

vm.getOrders = function (options) {
    return ordersService.getOrdersPage (options)
        .then(
         function(results) {
            console.log("results!");
            console.log(results);
        },
        function(error) {
            console.log("error!");
            console.log(error);
        });
};

如果您的服务中没有任何逻辑,那么您可以返回 $http 本身,因为 $http 反过来是一个承诺:

var _getPackagesPage = function (options) {

  var pageSize = options.data.pageSize;
  var page = options.data.page -1;

   return $http({
        method: 'get',
         url: serviceBase + 'api/Packages?pageSize=' + pageSize + '&page=' + page
      });

    };

【讨论】:

  • 这似乎向我的控制器返回了成功,即使它是 400。所以 options.success(results.data.Items) 返回 data = undefined。
  • 当您的服务返回 400 时,这将导致我们拒绝承诺的 .then 方法的错误回调。这不会在控制器中返回您的成功回调,而是会遇到错误 callbacj。
  • 然而事实并非如此。我已将尝试的修复和结果添加到开篇帖子中。
  • 你能验证它是否命中了 def.reject(ex);在服务中?
  • 它确实在击中 def.reject。 ex 包含状态:400,状态消息:“错误请求”。
【解决方案2】:

您的服务有太多回报。第二个没有被调用。

您无需手动创建承诺,因为 $http 返回 apromise。

您没有从您的服务返回数据。

var _getOrdersPage = function(options) {
        var pageSize = options.data.pageSize;
        var page = options.data.page -1;
        return $http({
            method: 'get',
            url: serviceBase + 'api/Packages?pageSize=' + pageSize + '&page=' + page
        })
        .then(
            function(results) {
                return results;
            },
            function(ex){
                return ex;
            });
}

你的控制器没问题,你可以使用 catch() 或者传递一个错误回调。

例子:

function myService($http) {
  this.getData = function(url) {
    return $http.get(url).
    then(function(response) {
      return response.data;
    }, function(error) {
      return error;
    });
  }
};

function MyController(myService) {
  var vm = this;  
  vm.result = [];
  vm.apiUrl = "https://randomuser.me/api/";
  myService.getData(vm.apiUrl).then(function (data) {
    vm.result = data;
  },
  function(error) {
    console.log(error);
  });
};

angular.module('myApp', []);
angular
    .module('myApp')
    .service('myService', myService)
    .controller('MyController', MyController);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.7/angular.min.js"></script>
<div ng-app="myApp">
  <div ng-controller="MyController as ctrl">
    {{ ctrl.result }}
  </div>
</div>

【讨论】:

    猜你喜欢
    • 2018-05-31
    • 1970-01-01
    • 2021-11-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-08-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多