【问题标题】:AngularJS TypeError: Cannot read property 'protocol' of undefinedAngularJS TypeError:无法读取未定义的属性“协议”
【发布时间】:2014-04-03 14:31:38
【问题描述】:

我已将 AngularJS 应用程序中的 $http > URL 参数从

       $http({ method:'POST',
                   url:'http://localhost/api/clients.php'
       }).success(function(data,status,headers,config){
                     deferred.resolve(data);
       }).error(function(data,status,headers,config){ 
                     deferred.reject(status);
       });

       $http({ method:'POST',
                   url: ConfigService.Urls.Clients
       }).success(function(data,status,headers,config){
                     deferred.resolve(data);
       }).error(function(data,status,headers,config){ 
                     deferred.reject(status);
       });

其中ConfigService如下:

Urls: {},
loadUrls: function(){
   Urls.Clients = 'http://localhost/api/clients.php';
}

当然,我在通过 .Resolve 加载控制器之前调用 loadUrls,所以我 100% 确定 Urls.Clients 不为空。

进行此更改后,我开始收到错误:

TypeError: Cannot read property 'protocol' of undefined
    at urlIsSameOrigin (http://localhost/myapp/app/lib/angular/angular.js:13710:17)
    at $http (http://localhost/myapp/app/lib/angular/angular.js:7508:23)

令人困惑的是,该应用程序运行良好,除了我遇到的那个错误......有人可以告诉我我在这里做错了什么吗?以及如果应用程序已经正常运行,为什么我会收到此错误。

【问题讨论】:

  • @drew_w 不,因为是不同的情况,这里我不拆分表头
  • 你能打完整的 $http 电话吗?
  • 基本上我在这里看到的唯一一件事是Urls.Clients 必须以某种方式是undefined。很抱歉一直在问问题 - 但是,loadUrls() 在哪里打电话?我在你的代码中没有看到。另外,如果你只是在服务中设置 URL,而不是把它放在一个函数中,那效果会更好吗?
  • @drew_w ConfigService 是一项服务,这就是加载 url 的地方,然后我会在需要时将此服务注入服务/控制器中。话虽如此,loadUrls 使用路由提供程序解析加载到第一个控制器(主页)加载

标签: angularjs


【解决方案1】:

这显然是订单问题。在第一次运行 $http 调用之后,loadUrls 才会被调用。这可能是因为控制器不一定按您期望的顺序加载 - 您不能指望路由提供程序在运行其他控制器之前打开并启动您的家庭控制器 - 这将取决于事情的设置方式。鉴于您在此处提供的代码量,就订单而言,很难说到底出了什么问题。

请记住,您有几个通用选项可以解决此问题:

  • 在运行$http 请求之前始终调用loadUrls()。这并不优雅,但可以解决问题
  • 将您的所有$http 调用和loadUrls() 封装在该封装中。这比上一个稍微好一点,因为如果您需要更改 loadUrls() 或确保仅在以后可以实现该逻辑时调用它。
  • 您已经观察到这一点,但是您可以将初始化更改为直接在服务中进行,而不是在服务提供的例程中进行。这将解决问题,尽管它可能会让您在每次 url 更改时都必须更新服务的地方。
  • 忍受错误,知道当控制器加载时它将实例化并在该时间点获取正确的数据。我不经常喜欢这样的解决方案,因为它可能会导致以后难以追踪的错误,但如果您不喜欢以前的任何选项,这在技术上是可以的。
  • 使用应用配置,在应用加载时执行(注意并非所有资源都已初始化且不允许注入)。一个例子from the documentation

    angular.module('myModule', []).
      config(function(injectables) {
          // provider-injector
          // This is an example of config block.
          // You can have as many of these as you want.
          // You can only inject Providers (not instances)
          // into config blocks.
      }).
    

    你可以使用这个或运行块来初始化你想要的东西

我确信还有其他选项,具体取决于您的代码结构,但希望这至少可以帮助您入门。祝你好运!

【讨论】:

  • 你是对的,发生的情况是 $http 调用返回了一个承诺,但导致错误的代码在承诺完成之前运行。有没有办法可以在应用程序启动时调用 $http 并在承诺失败时阻止应用程序运行?
  • @MChan 我添加了另一个选项,它可能会满足您的需求。因为 Angular 本身正在初始化,所以您无能为力,但 runconfig 可能会让您走得更远。
  • 我无法在配置中注入我的服务,因此没有多大帮助
  • @MChan 你试过.run吗?
  • .run 不会有任何区别,我的意思是同样的问题存在,即使承诺失败,它仍然会在运行部分继续运行代码
【解决方案2】:

我遇到了同样的问题,我通过改变这个来解决它:

    var logoutURL = URL + '/logout';
    function sendLogoutHttp(){
        return $http({
            method: 'GET',
            url: logoutURL,
            headers: {'Content-Type': 'application/x-www-form-urlencoded'}
        });
    }

到这里

    function sendLogoutHttp(){
        var logoutURL = URL + '/logout';
        return $http({
            method: 'GET',
            url: logoutURL,
            headers: {'Content-Type': 'application/x-www-form-urlencoded'}
        });
    }

【讨论】:

    猜你喜欢
    • 2014-02-16
    • 2015-08-26
    • 2016-09-12
    • 2016-11-20
    • 1970-01-01
    • 1970-01-01
    • 2016-09-05
    • 2014-12-24
    • 2015-03-28
    相关资源
    最近更新 更多