如何从控制台测试 AngularJS 服务?

Posted

技术标签:

【中文标题】如何从控制台测试 AngularJS 服务?【英文标题】:How can I test an AngularJS service from the console? 【发布时间】:2013-03-09 19:12:31 【问题描述】:

我有这样的服务:

angular.module('app').factory('ExampleService', function()
  this.f1 = function(world)
    return 'Hello '+world;
  
  return this;
)

我想从 JavaScript 控制台测试它并调用服务的函数f1()

我该怎么做?

【问题讨论】:

【参考方案1】:

TLDR:在一行中您要查找的命令:

angular.element(document.body).injector().get('serviceName')

深潜

AngularJS 使用 依赖注入 (DI) 将服务/工厂注入到您的组件、指令和其他服务中。所以获取服务需要做的是先获取AngularJS的injector(injector负责连接所有的依赖,并提供给组件)。

要获取应用的 injector,您需要从 Angular 正在处理的元素中获取它。例如,如果您的应用注册在 body 元素上,您调用 injector = angular.element(document.body).injector()

从检索到的injector 中,您可以使用injector.get('ServiceName') 获得您喜欢的任何服务

有关此答案的更多信息:Can't retrieve the injector from angular 还有更多:Call AngularJS from legacy code


获取特定元素的$scope 的另一个有用技巧。 使用开发人员工具的 DOM 检查工具 选择元素,然后运行以下行($0 始终是选定元素):angular.element($0).scope()

【讨论】:

我也必须这样做才能使其工作。顺便说一句,angular.element('*[ng-app]').injector() 应该适用于所有情况。 如果执行 angular.element('html') 时出现错误“选择器未实现”,则可以使用 Chrome $0 功能。选择 html 元素,转到控制台并运行 angular.element($0).injector() document 也可以:angular.element(document).injector().get('serviceName') 仅供参考,我必须在 chrome 上使用 document.body 仅供参考,我想使用 $location 服务,但最终我需要将它包装在 scope.apply 中。我知道这是有据可查的,但它让我忘记了。在一行中 angular.element(document).scope().$apply(angular.element(document).injector().get('$location').path('/my/angular/url'))跨度> 【参考方案2】:

首先,您的服务的修改版本。

一)

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

app.factory('ExampleService',function()
    return 
        f1 : function(world)
            return 'Hello' + world;
        
    ;
);

这会返回一个对象,这里没什么新的。

现在从控制台获取这个的方法是

b)

var $inj = angular.injector(['app']);
var serv = $inj.get('ExampleService');
serv.f1("World");

c)

您之前在那里做的一件事是假设 app.factory 会返回函数本身或它的新版本。事实并非如此。为了得到一个构造函数,你要么必须做

app.factory('ExampleService',function()
        return function()
            this.f1 = function(world)
                return 'Hello' + world;
            
        ;
    );

这将返回一个 ExampleService 构造函数,接下来您必须对其执行“新建”操作。

或者,

app.service('ExampleService',function()
            this.f1 = function(world)
                return 'Hello' + world;
            ;
    );

这会在注入时返回新的 ExampleService()。

【讨论】:

当我执行var $inj = angular.injector(['app']); 时,控制台会在一个应用程序中抛出Error: Unknown provider: $filterProvider from app,在另一个应用程序中抛出Error: Unknown provider: $controllerProvider from app... @JustGoscha 您的应用程序是如何配置的?即一条线(看起来像)如何 var app = angular.module('app',[]);看起来像在您的应用中。 我没有完全理解这个问题..看起来就像你说的angular.module('app',[]);,然后在不同的文件中有服务、控制器等,它们都被定义为angular.module('app').factory('FeatureRegistry',function()//code here);,例如 @JustGoscha 这是我为测试所做的。我用 chrome 访问了docs.angularjs.org/api。打开控制台。在我答案的 a 部分输入代码,然后在 b 部分输入代码。您应该会看到 Hello World.. 您可以尝试一下吗? @JustGoscha - 是的,这是因为它忽略了 Angular 的生命周期。它不会在允许它运行之前等待服务创建,因此如果在注入器调用下声明了服务,它不会看到服务已定义。【参考方案3】:

@JustGoscha 的答案很准确,但是当我想访问时要输入很多内容,所以我将它添加到我的 app.js 的底部。然后我只需输入x = getSrv('$http') 即可获得http 服务。

// @if DEBUG
function getSrv(name, element) 
    element = element || '*[ng-app]';
    return angular.element(element).injector().get(name);

// @endif

它将它添加到全局范围,但仅在调试模式下。我将它放在@if DEBUG 中,这样我就不会在生产代码中使用它。 I use this method to remove debug code from prouduction builds.

【讨论】:

【参考方案4】:

Angularjs 依赖注入框架负责将应用模块的依赖注入到控制器中。这可以通过其注射器实现。

您需要首先识别 ng-app 并获取关联的注入器。 下面的查询可以在 DOM 中找到您的 ng-app 并检索注入器。

angular.element('*[ng-app]').injector()

但是,在 chrome 中,您可以指向目标 ng-app,如下所示。并使用$0 hack 并发出angular.element($0).injector()

一旦你有了注入器,就可以得到如下的依赖注入服务

injector = angular.element($0).injector();
injector.get('$mdToast');

【讨论】:

以上是关于如何从控制台测试 AngularJS 服务?的主要内容,如果未能解决你的问题,请参考以下文章

从angularjs中的服务调用控制器函数

如何使用 AngularJS 的 $resource 和 spring rest 控制器获取布尔值

AngularJS 从控制器触发并观察服务中的对象值变化

在浏览器控制台中使用 Angularjs $http

AngularJS:如何从控制器功能切换视图?

在AngularJs中从控制器调用服务时,从$ get factory方法返回一个值