Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/389.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript AngularJS-使用$routeProvider:resolve拒绝了$http承诺_Javascript_Angularjs - Fatal编程技术网

Javascript AngularJS-使用$routeProvider:resolve拒绝了$http承诺

Javascript AngularJS-使用$routeProvider:resolve拒绝了$http承诺,javascript,angularjs,Javascript,Angularjs,我试图在$routeProvider中使用resolve仅在$http请求完成时显示新路由。如果请求成功,则解析$http.post()产生的承诺并呈现视图。但如果请求失败(例如超时或内部错误),则承诺永远不会得到解决,视图也永远不会呈现。如何使用resolve处理请求失败 代码中最重要的部分如下所示: app.js $routeProvider.when('/warrantyResult', { templateUrl : 'partials/warranty-result.html'

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

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

app.js

$routeProvider.when('/warrantyResult', {
    templateUrl : 'partials/warranty-result.html',
    controller : 'WarrantyResultCtrl',
    resolve : {
        response : [ 'Warranty', function(Warranty) {
            return Warranty.sendRequest();
        } ]
    }
});
controllers.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();
} ]);
services.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调用使用承诺,即使请求失败也可以解决它,但我想知道是否有更简单的解决方案


感谢您的阅读和帮助:)

经过深入搜索,我无法找到解决此问题的方法

我决定在我的路由定义中删除resolve station,并在QuartyCtrl中使用以下代码片段

$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');
        });
    }
};

不是很聪明,但工作的意图。。。如果有人仍然有原始问题的解决方案,我将非常高兴地阅读它

我认为从
resolve
执行此操作的唯一方法是手动解析
保修返回的承诺。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;

  } ]
}
保修ResultCtrl
中,您可以检查是否发生错误并生成重定向

编辑:更干净的解决方案:

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

()

我发现,如果
承诺被
拒绝,那么控制器根本不会被触发,并且您的视图从未被呈现过——与您一样

我还发现,如果您使用
.then()
$routeProvider
解析中处理
承诺
,那么
.then()
将返回一个新的
承诺
,即
已解析
,并且您的控制器将被触发,尽管没有您期望的数据

例如:

$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?
                });
        }]
    }
});
现在,在控制器中,您需要检查
响应
是否为
未定义
。如果
未定义
,则您将知道调用
Warranty.sendRequest()
失败,您可以采取相应措施

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

更新
刚刚注意到,您在控制器中注入的是
保修
服务,而您应该注入您在
解决
中定义的
响应
。这将阻止您的视图呈现,直到从
Warranty.sendRequest()
返回的承诺得到解决。

取决于您希望您的应用程序在解决失败时表现如何?最好的行为是在解决失败时将用户重定向到不同的路径(/requestError?)。或者可以提供/warrantyResult,并且此路由的控制器将负责检查请求是否成功。您的plunker不工作。但无论如何,谢谢你的回答!我要试试你的解决办法。@pdegand59哎呀,对不起!显然,我昨天清理的内容有点太多了:(我们只有
$location.path('/webservicererror')
,并在
$http
调用的错误处理程序中执行。这样,您就可以进行路由解析,而不必考虑拒绝的承诺,因为它将在服务中处理