【问题标题】:Correct method to Redirect from $http.post in angularjs从 angularjs 中的 $http.post 重定向的正确方法
【发布时间】:2017-03-04 07:15:33
【问题描述】:

如果 $http.post 返回特定的错误代码,你能告诉我重定向到另一个页面的正确方法是什么吗?

只是为了添加上下文,如果用户未登录或未授权使用 API,我想重定向到另一个页面。

  function getData(filter) {
     var deferred = $q.defer();
     var data = JSON.stringify(filter);

      $http.post('/myapp/api/getData', data)
         .success(function (data, status, headers, config) {
            deferred.resolve(data);
         })
              .error(function (error) {
                 deferred.reject(error);
              });

     return deferred.promise;
  }

【问题讨论】:

标签: angularjs asp.net-web-api


【解决方案1】:

您可以根据您的错误情况使用 $window.location.href 重定向到该页面。

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

app.controller("sampleController", [
  "$scope",
  '$window',
  'sampleService',
  function($scope, $window, sampleService) {
    sampleService.getData().then(function(result) {}, function(error) {
      if (error.statusCode === 400) {
        alert("Error");
        $window.location.href = "http://stackoverflow.com"
      }
    });
  }
]);
app.service("sampleService", function() {
  this.getData = function() {
    var promise = new Promise(function(resolve, reject) {
      setTimeout(function() {
        reject({
          statusCode: 400
        });
      }, 1000);
    });
    return promise;
  }
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-App="sampleApp">
  <div ng-controller="sampleController">
  </div>
</div>

【讨论】:

  • 我可以有一个 else 与 deferred.reject(error);在 $window.location.href 之后?
  • 我不明白你的意思?能详细点吗?
  • 所以对于一个特定的错误我想“重定向”。但对于所有其他人,我想 deferred.reject(error);这行得通吗?
  • 这正是我在控制器 .then 方法中的 errorCode 检查到 400 的内容。通常,服务并不意味着在收到的响应上存在分歧。服务职责是拨打电话并返回。由控制器读取并决定如何处理它收到的数据。通过这样做,您的服务是独立的并且可以重用。如果不是,特定服务只能与不建议使用的控制器配合使用。
【解决方案2】:

捕获全局AuthenticationErrorin 角度的最佳方法是使用拦截器。 这样您就可以监控从 angular 发送的所有请求并检查AuthenticationError。

$provide.factory('AuthErrorInterceptor', function($q, $location) {
  return {
   'responseError': function(rejection) {

        //check for auth error

        $location.path('/login');

        return $q.reject(rejection);
    }
  };
});

【讨论】:

    【解决方案3】:

    例子:

      $http.post('/myapp/api/getData', data)
         .then(function (data) {
             if(data.ErrorCode==1)
            {
                 $window.location.href="controllerName/actionName";
            }
         })
    

    【讨论】:

      【解决方案4】:

      使用拦截器服务将您的所有拒绝请求集中在同一个服务中。

      module.config(['$httpProvider', ($httpProvider: ng.IHttpProvider) => {
          $httpProvider.interceptors.push('errorService');
      }]);
      
      
      module.factory('errorService', ['$location', function($location) {  
         var errorService = {
             responseError: function(rejection) {
                 if (rejection === '401') {
                     $location.path('/login');
                 }
             }
          };
          return errorService;
      }]);
      

      【讨论】:

        【解决方案5】:

        $http.post 具有误导性。 到目前为止,最好的答案是@Kliment's。拦截器是管理 http 请求前后的最佳方式。

        但是,如果您的最终目标是阻止对某个页面的访问,您必须至少使用一个路由插件(ngRoute,ui-router),因为按照承诺的想法,总会有一个http请求和响应之间的延迟。

        根据服务器响应时间,您仍然会看到页面显示大约一秒钟左右。

        使用 ui-router,您只需为要保护的每个状态配置 resolve 方法。它可能看起来像这样:

        .state('protected',
        {
            url : '/protected_page',
            templateUrl : 'secret.html',
            resolve: {
                loggedin: loggedin
            }
        })
        

        loggedin 是指您定义的包含您的 $http.post 调用(或更好的服务)的函数

        function loggedin($timeout, $q, $location, loginService) {
            loginService.then(function(data) {
                if(data.status == 401) {
                    //$timeout(function() { $location.path('/login'); });
                    return $q.reject();
                } else {
                    return $q.when();
                }
            });
        }
        

        这里这个特定的服务返回一个 401 状态,但你可以返回任何东西。

        在接受或拒绝之前,状态不会得到解决(并且页面不会显示)。

        如果你愿意,你可以直接从那里重定向,虽然它不是很优雅。 ui-router 为您提供了另一种默认重定向选项:

        if (tokenIsValid()) 
            $urlRouterProvider.otherwise("/home");
        else
            $urlRouterProvider.otherwise("/login");
        

        otherwise 告诉 ui-router 如果特定请求不存在状态或解析已被拒绝,则转到某些 url。

        在另一个主题上,您的http request 写得不好。

        .success 和 .error 已弃用,您无需在 $http 请求上创建承诺 ($q)它本身已经返回了一个承诺。

        您在上面链接的文档中有一个很好的例子。

        【讨论】:

          【解决方案6】:

          您可以根据可以从 API 调用返回的状态代码重定向到用户未经授权访问的页面。

          $http({
          method: "POST",
          url: 'Api/login',
          headers: {'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'}
          }).success(function (data,status) {
          if(status==200){
              alert('Successfully logged in');
              $location.path('/dashboard'); //You can use this if you are defined your states.
          }
          }).error(function (data,status) {
              if(status==403||status==403){ //Based on what error code you are returning from API
               $location.path('/login');// if states are defined else
               $window.location.href = "https://www.google.com";
              }
          });
          

          【讨论】:

            【解决方案7】:

            首先很好的问题,在这种情况下你可以使用 $location , $state 如果是外部 url 你可以使用 $window.location.href .. . 我会推荐 $location ,这是最好的方式...

            更多详情请查看链接Using $window or $location to Redirect in AngularJS

                function getData(filter) {
                     var deferred = $q.defer();
                     var data = JSON.stringify(filter);
            
            
            
                $http.post('/myapp/api/getData', data)
                         .success(function (data, status, headers, config) {
                            deferred.resolve(data);
            
            if(data.errorcode==9999)  // Define Your  Error Code in Server
            {
            
                $location.path('/login'); // You Can Set Your Own Router 
            
            }             })
                              .error(function (error) {
            
                $location.path('/login'); // You Can Set Your Own Router 
                                 deferred.reject(error);
                              });
            
                     return deferred.promise;
                  }
            

            最好使用 $location 或 $state ...

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2015-06-17
              • 2017-04-02
              • 2010-10-23
              • 1970-01-01
              • 2015-02-07
              • 2021-11-01
              • 2018-06-20
              • 1970-01-01
              相关资源
              最近更新 更多