当前位置: 首页 > 面试题库 >

我需要两个AngularJS $ http服务实例还是什么?

颜杰
2023-03-14
问题内容

我想将响应拦截器添加到$ http服务中以进行错误处理。拦截器逻辑包括在必要时使用$ http向服务器发送错误消息, 但是
我不想向服务器发送有关错误消息的错误消息,我的意思是,我想在向服务器发送错误消息时禁用拦截器。

我的想法是创建一个名为“ remote_log”的服务,并将将错误发送到服务器所需的所有代码放入其中。该服务当然将使用$
http服务,并将其放在其依赖项列表中。

然后将拦截器的依赖项添加到“ remote_log”服务中,并在需要向服务器发送错误时在拦截器内部使用“ remote_log”。问题是:

当$ http服务仍然无法实例化/访问时,必须使用$ httpProvider定义拦截器,因此,在拦截器代码内部不能与$
http服务相关,因为会发生“循环依赖”错误。

我认为我唯一的选择是在“ remote_log”中创建$ http服务的单独实例,该实例不使用我在创建拦截器时设置的$
httpProvider配置。我的问题是:我该怎么做?还有其他想法吗?


问题答案:

那么,为什么会出现错误?这是该过程的快速概述:

  1. $ http服务已请求。
  2. $ httpProvider被要求构造它。
  3. 在构造过程中,您注册了拦截器,该拦截器请求$ http服务尚不存在。
  4. 您收到“循环依赖”错误。

第一个解决方案。

使用angular.injector()创建依赖项。注意,您将创建另一个$ http服务,与您的应用程序无关。

$httpProvider.interceptors.push(function($q) {
    $injector = angular.injector();
    return {
        response: function(response) {
            $injector.invoke(function($http) {
                // This is the exterior $http service!
                // This interceptor will not affect it.
            });
        }
    };
});

第二个解决方案(更好)。

将$ injector注入拦截器中,并在$ http初始化后使用它来检索依赖项,就在您需要它们时。这些依赖项是您应用程序的注册服务,不会重新创建!

$httpProvider.interceptors.push(function($q, $injector) {
    return {
        response: function(response) {
            $injector.invoke(function($http, someService) {
                // $http is already constructed at the time and you may
                // use it, just as any other service registered in your
                // app module and modules on which app depends on.
            });
        }
    };
});

2.防止拦截问题。

如果使用第二种解决方案,则实际上存在两个问题:

  1. 如果在拦截器内部使用$ http服务,则可能会遇到无限的拦截:发送请求,拦截器捕获请求,发送另一个请求,捕获另一个请求,再次发送,依此类推。
  2. 有时您只想防止请求被拦截。

$ http服务的’config’参数只是一个对象。您可以创建一个约定,提供自定义参数并在拦截器中识别它们。

例如,让我们在配置中添加“ nointercept”属性,然后尝试重复每个用户请求。这是一个愚蠢的应用程序,但却是了解行为的有用示例:

$httpProvider.interceptors.push(function($q, $injector) {
    return {
        response: function(response) {
            if (response.config.nointercept) {
                return $q.when(response); // let it pass
            } else {
                var defer = $q.defer();
                $injector.invoke(function($http) {
                    // This modification prevents interception:
                    response.config.nointercept = true;
                    // Reuse modified config and send the same request again:
                    $http(response.config)
                        .then(function(resp) { defer.resolve(resp); },
                              function(resp) { defer.reject(resp); });
                });
                return defer.promise;
            }
        }
    };
});

在拦截器中进行属性测试后,您可以防止控制器和服务中的拦截:

app.controller('myController', function($http) {
    // The second parameter is actually 'config', see API docs.
    // This query will not be duplicated by the interceptor.
    $http.get('/foo/bar', {nointercept: true})
        .success(function(data) {
            // ...
        });

});


 类似资料:
  • 问题内容: 我有一个称为“播放器”的服务,并且在Flash对象完成加载后需要更新该服务。 我知道如何使用 但是当我需要更新模块中已经创建的实例时,它将返回“玩家”的新实例。有没有办法做到这一点?我只想要播放器的一个实例,但是我需要从外部javascript对其进行初始化。 问题答案: 好吧,我真的看不到您正在做的所有事情,但是您大概只有1/2处。 这是我要描述的工作总结 应该返回与应用程序中的服务

  • 本文向大家介绍为什么我们需要微服务容器?相关面试题,主要包含被问及为什么我们需要微服务容器?时的应答技巧和注意事项,需要的朋友参考一下 要管理基于微服务的应用程序,容器是最简单的选择。它帮助用户单独部署和开发。您还可以使用Docker将微服务封装到容器的镜像中。没有任何额外的依赖或工作,微服务可以使用这些元素。

  • 问题内容: 在参考资料中,我读到: 最后,重要的是要意识到所有Angular服务都是应用程序单例。这意味着每个喷油器只有一种给定服务的实例。 但是用这个简单的代码似乎不是一个单例 我有点困惑,你能解释一下我怎么了吗? 更新1 可能不是我不是棚里最犀利的工具,但是在@Khanh TO答复之后,这在参考文献中会是一个更好的解释,尚不十分清楚。 更新2 BOOM,这是一个单身人士! 更新3 但是如果你喜

  • 问题内容: 我的应用程序中有一个弹出模式服务,名为。它只是在上翻转了一些布尔值,从而导致2条指令正确显示/隐藏。这是显示新模态时调用的函数 如您所见,我显示不透明的背景,然后设置了一个名为的变量,该变量随后通过DI传递到我的指令中。但是后来我注意到我的模态没有出现在适当的时候,而是在变量设置为true 之后出现在NEXT摘要循环中。然后,我必须添加作业周围的内容才能使其正常工作。但是,我认为仅当我

  • 问题内容: 用uWSGI和Nginx设置Flask是非常困难的,即使使用扩展脚本也需要花费一些时间,并且必须记录到指令中以备后用。 如果我不打算在服务器上增加很大的负载(它对公共隐藏),那么在没有uWSGI的情况下运行它是否有意义?(Flask可以监听端口。Nginx可以转发请求吗?) 只在端口上运行裸瓶应用程序,甚至不使用Nginx是否有意义? 问题答案: 当你“运行Flask”时,你实际上是在

  • 随着新的工具栏小部件的引入和AppCompat(android.support.v7.widget.Toolbar)版本的推出,是否还需要调用setSupportActionbar(工具栏)?或者调用setSupportActionbar有什么好处吗;现在我们可以设置标题、子标题、导航图标、导航图标单击侦听器(getSupportActionBar()。直接在工具栏上设置DisplayHomeAs