Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/478.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 配置服务(通过其提供程序)以使用其他服务_Javascript_Angularjs - Fatal编程技术网

Javascript 配置服务(通过其提供程序)以使用其他服务

Javascript 配置服务(通过其提供程序)以使用其他服务,javascript,angularjs,Javascript,Angularjs,我有一个服务,我想通过传入一个函数来配置它。只要此函数返回我的服务可以使用的内容,它就不关心如何获取数据,也不关心同步/异步。以下是我希望能够做到的一个示例,但由于明显的原因无法做到: .config(function(MyServiceProvider, OtherService) { MyServiceProvider.setSomeMethod( OtherService.someMethod ); }) 这太棒了,但是似乎没有一种方法可以从config函数中引用“OtherSe

我有一个服务,我想通过传入一个函数来配置它。只要此函数返回我的服务可以使用的内容,它就不关心如何获取数据,也不关心同步/异步。以下是我希望能够做到的一个示例,但由于明显的原因无法做到:

.config(function(MyServiceProvider, OtherService) {

  MyServiceProvider.setSomeMethod( OtherService.someMethod );

})
这太棒了,但是似乎没有一种方法可以从config函数中引用“OtherService”。我知道这是因为
OtherService
可能尚未配置,因此它的实例不应该存在,但在这种情况下,一个人该怎么办

在运行块中建立这种关联(带焦虑)合适吗

.run(function(MyService, OtherService) {

  MyService.setSomeMethod( OtherService.someMethod );

})
在引导解决之后,使用该服务解决依赖关系

例如:

angular.module('myApp').config(function(myProvider) {
  myProvider.setMethod('myUberMethod');
});

// Somewhere in myProvider

var theUberMethod, theUberMethodName;

function setMethod(dependencyName) {
  theUberMethodName = dependencyName;
}

function performTheMethod() {
  theUberMethod = theUberMethod || $injector.get(theUberMethodName);

  // Magic

  theUberMethod();
}
您甚至可能想看看$injector的invoke方法,因为它允许您将参数注入到被注入的函数方法中

编辑 我得好好解释一下

您面临的问题与注入模块未在配置阶段初始化有关,因此无法将服务注入配置函数。只允许提供程序。您必须将任何依赖项解析推迟到配置阶段之后。这可以通过在提供者上使用$get函数来完成,或者通过注入$injector服务并使用它来完成解析

一个函数可以注册为依赖项注入,就像任何其他对象一样。因此,向提供者提供函数的名称就足以让它在以后解析并执行它

myApp.provider('myFunctionCallee', function() {

  var self = this;

  return {
    hookMyFunction: function(value /* string: name of the function */ ) {
      self.myFunction = value;
    },
    $get: function($injector) {
      return {
        executeMyFunction: function() {
          return $injector.get(self.myFunction)();  
        }
      };
    }
  };
});
现在我们需要一种方法来通知喷油器该功能

例一 这是最简单的。。。只需直接向注入器注册一个函数(对象)。我们将通过请求“myFunction”来解析函数

myApp.value('myFunction', function() { 
  return 'hello injected function!';
});

myApp.config(function(myFunctionCalleeProvider) {
  myFunctionCalleeProvider.hookMyFunction('myFunction');
});
例二 此方法看起来与前一种方法非常相似。我们将直接注册一个函数,但也将它注入到我们的目标服务中

myApp.value('myFunction', function() {
  return 'hello injected service function 1';
});

myApp.factory('myService', function(myFunction) {
  return {
    myServiceFunction: myFunction
  };
});

myApp.config(function(myFunctionCalleeProvider) {
  myFunctionCalleeProvider.hookMyFunction('myFunction');
});
例三 有时,前面的方法是不可能的。也许代码是由其他人编写的,而他/她没有你这样的远见卓识。但是,我们可以在任何可注入对象上公开任何函数:

myApp.factory('myService', function() {
  return {
    // We want to target this beast
    myServiceFunction: function() {
      return 'hello injected service function 2';
    }
  };
});

// Inject the target service here ...
myApp.factory('myFunction', function(myService) {
  // ... and expose the beast.
  return myService.myServiceFunction;
});

myApp.config(function(myFunctionCalleeProvider) {
  myFunctionCalleeProvider.hookMyFunction('myFunction');
});

你可以在这里看到、感受和舔它。

这两个答案都是@null答案的衍生物。为了完整性和清晰性,我把这个放在这里。我认为这个话题在其他地方没有得到很好的讨论,可能很难让人理解(就像我的情况一样)

在我下面不太喜欢的第二种方法中,我使用
$q.when()
包装此处的主题所配置的函数。我建议在这种情况下始终使用它,以便配置的函数可以安全地同步或异步。为了降低复杂性,我在第一个示例中不考虑这一点

创建一个服务并按名称(字符串)传递对该服务的引用。 使用引用其他服务的字符串名称配置提供程序-以何种方式或可能不是您实际尝试访问的服务:

.config(function(SomeServiceProvider) {
  SomeServiceProvider.someServiceName = 'ThisService';
})
ThisService
将被
SomeService
作为函数调用
ThisService
可以将多个其他服务注入其中,对它们执行一些操作并返回结果

.factory('ThisService', function(FooService, BarService) {
  var service = function() {
    var x = FooService.whatever();
    var y = BarService.blah();
    return x+y;
  };
  return service;
})
在您配置的
SomeService
中,使用
$injector
获取
此服务

.provider('SomeService', [
  function() {

    var config = this;

    this.someServiceName = null;

    this.$get = [
      '$injector',
      factory
    ];

    function factory($injector) {

      var service = function() {
        //do stuff
        //call the configured function
        var fn = $injector.get(config.someServiceName);
        var myData = fn();
        //etc
      };

      return service;

    }

  }
])
我目前正在使用一个默认函数对此进行扩展,如果配置中没有给出服务名称,将调用该函数:

.provider('SomeService', [
  function() {

    var config = this;

    this.defaultFn = function() {
      //default stuff
    };

    this.someServiceName = null;

    this.$get = [
      '$injector',
      factory
    ];

    function factory($injector) {

      var service = function() {
        //do stuff

        //use defaultFn if no service name was given
        var fn = config.someServiceName
          ? $injector.get(config.someServiceName)
          : config.defaultFn
        ;
        var myData = fn();
        //etc
      };

      return service;

    }

  }
])
这种方法有一个小小的缺点,就是它创建了另一个命名的角度组件(服务),但这其实不是问题,除非你非常不擅长命名或非常不走运。我只是在服务名称的开头添加了“Config”,对名称空间进行排序并对其进行标记

另一个选项:将$injector传递给在配置中创建的函数。 这是我以前的答案,我更喜欢上面的解决方案

(此处使用的
$q
与问题无关。我之所以包含它,是因为它与功能非常相关-配置的服务可以使用同步或异步功能。)


您可以从另一个服务传递方法名并在配置中绑定它-将“someMethod”作为methodName传递,然后调用
OtherService[methodName]
-尽管我同意这很令人沮丧,而且肯定是您期望的一个带有dicto do的fw。@BenjaminGruenbaum好主意,但该服务甚至不知道其他服务。我可以尽快执行
myService.setSomeMethod(函数(){return'whatever})。碰巧我想在这里使用另一个服务的方法。这假设配置的服务期望涉及另一个服务。没有。它只需要一个函数,而不关心函数做什么。我进一步考虑了这个想法,将
$injector
传递给我在config函数中声明的函数。这使得进行配置的人可以随心所欲。您误解了:函数是对象,因此是可注入的。我可能仍然误解:)您的方法似乎使用函数或作为函数的服务。。如果你想将方法设置为
SomeService.somesmethod
,那你就不走运了,对吧?我的坏消息是,还不清楚--这里已经很晚了。请看一下编辑。
.config([
  'MyServiceProvider',
  function(MyServiceProvider) {

    MyServiceProvider.setSomeMethod(function($injector) {
      var OtherModule = $injector.get('OtherModule');
      OtherModule.someMethod();
    });

  }
])

.provider('MyService', [
  function() {

    var config = this;

    this.someMethod = function() { };

    this.setSomeMethod = function(fn) {
      this.someMethod = fn;
    };

    this.$get = [
      '$q',
      '$injector',
      factory
    ];

    function factory($q, $injector) {

      var service = function() {
        var loaded = config.someMethod($injector);
        $q.when(loaded).then(function() {

        });
      };

      return service;

    }

  }
])