13

我试图resolve在 a中使用仅在请求完成$routeProvider时显示新路由。$http如果请求成功,则 $http.post() 产生的承诺被解析并呈现视图。但是如果请求失败(例如超时或内部错误),promise 永远不会解决,视图也永远不会呈现。如何使用 处理请求失败resolve

代码中最重要的部分如下:

应用程序.js

$routeProvider.when('/warrantyResult', {
    templateUrl : 'partials/warranty-result.html',
    controller : 'WarrantyResultCtrl',
    resolve : {
        response : [ 'Warranty', function(Warranty) {
            return Warranty.sendRequest();
        } ]
    }
});

控制器.js

angular.module('adocDemo.controllers', []).controller('HomeCtrl', [ '$scope', function($scope) {

} ]).controller('WarrantyCtrl', [ '$scope', '$http', '$location', 'Warranty', function($scope, $http, $location, Warranty) {
    $scope.submitWarranty = function() {
        $scope.loading = true;
        Warranty.setRequestData($scope.data);
        $location.path('/warrantyResult');
    };
} ]).controller('WarrantyResultCtrl', [ '$scope', 'Warranty', function($scope, Warranty) {

    $scope.request = Warranty.getRequestData();
    $scope.response = Warranty.getResponseData();
} ]);

服务.js

angular.module('adocDemo.services', []).factory('Warranty', [ '$http', '$timeout', function($http, $timeout) {
    /**
     * This service is used to query the Warranty Webmethod. The sendRequest
     * method is automaticcaly called when the user is redirected to
     * /warrantyResult route.
     */
    var isDataSet = false;
    var requestData = undefined;
    var responseData = undefined;
    return {
        setRequestData : function(data) {
            //Setting the data
            isDataSet = true;
        },
        getRequestData : function() {
            return requestData;
        },
        sendRequest : function(data) {
            if(isDataSet) {
                var request = $http.post('url/to/webservice', requestData);
                request.success(function(data) {
                    responseData = data;
                });
                return request;
            }   
        },
        getResponseData : function() {
            return responseData;
        }
    };
} ]);

我知道即使请求失败,我也可以在 $http 调用周围使用承诺并解决它,但我想知道是否有更简单的解决方案。

感谢您的阅读,希望对您有所帮助:)

4

3 回答 3

8

我认为这样做的唯一方法resolve是手动解决返回的承诺并将Warranty.sendRequest其重新包装在一个新的承诺中:

resolve : {
  response : [ 'Warranty' '$q', function(Warranty, $q) {
    var dfd = $q.defer();

    Warranty.sendRequest().then(function(result) {
      dfd.resolve({ success: true, result : result });
    }, function(error) {
      dfd.resolve({ success : false, reason : error });
    });

    return dfd.promise;

  } ]
}

WarrantyResultCtrl中,您可以检查是否发生错误并生成重定向。

编辑:更清洁的解决方案:

// WarrantyCtrl
$scope.$on('$routeChangeError', function() {
  // handle the error
});
$scope.submitWarranty = function() {
    $scope.loading = true;
    Warranty.setRequestData($scope.data);
    $location.path('/warrantyResult');
};

plunker 演示

于 2013-06-10T14:54:42.330 回答
3

我发现如果 is 根本不会触发控制器Promiserejected并且您的视图永远不会呈现 - 与您相同。

我还发现,如果您在's中处理Promisea ,则将返回一个新的that并且您的控制器毕竟会被触发,尽管没有您期望的数据。.then()$routeProviderresolve.then()Promiseresolved

例如:

$routeProvider.when('/warrantyResult', {
    templateUrl : 'partials/warranty-result.html',
    controller : 'WarrantyResultCtrl',
    resolve : {
        response : [ 'Warranty', function(Warranty) {
            return Warranty.sendRequest()
                .then(null, function(errorData) {
                    // Log an error here?
                    // Or do something with the error data?
                });
        }]
    }
});

现在在您的控制器中,您将要检查是否responseundefined. 如果是,undefined那么您将知道调用Warranty.sendRequest()失败,并且您可以采取相应的行动。

对于它的价值,我没有走这条路。相反,我将$location服务注入处理程序并在调用被拒绝resolve时重定向到错误页面。$http

更新 刚刚注意到,在您的控制器中,您正在注入Warranty服务,而您应该注入response您在resolve. 这将阻止您的视图呈现,直到从返回的 PromiseWarranty.sendRequest()得到解决。

于 2013-12-13T20:35:43.480 回答
0

经过深入搜索,我找不到这个问题的解决方案。

我决定在我的路由定义中删除 resolve 语句,并在 WarrantyCtrl 中使用以下代码片段。

$scope.submitWarranty = function() {
    $scope.formatUserData();
    if ($scope.verifyUserData()) {
        $scope.loading = true;
        Warranty.setRequestData($scope.data);
        Warranty.sendRequest().success(function() {
            $location.path('/warrantyResult');
        }).error(function() {
            $location.path('/webserviceError');
        });
    }
};

不是很聪明,但按意图工作......如果有人仍然有原始问题的解决方案,我会很高兴阅读它!

于 2013-06-10T13:44:02.690 回答