Javascript 函数式编程中的依赖注入

Javascript 函数式编程中的依赖注入,javascript,dependency-injection,Javascript,Dependency Injection,通过一个例子可以更好地说明这个问题。我将使用Javascript(实际上是为了语法的缘故而使用Coffeescript),但仅仅因为Javascript只是另一种,对吗 因此,假设我正在编写一个web应用程序,它(显然)执行ajax请求。我实现了一个函数来处理: ajaxRequest = (url, params, callback) -> # implementation goes here 现在,假设我有一个从服务器获取数据的网格。在我的代码中,我必须执行以下操作: use

通过一个例子可以更好地说明这个问题。我将使用Javascript(实际上是为了语法的缘故而使用Coffeescript),但仅仅因为Javascript只是另一种,对吗

因此,假设我正在编写一个web应用程序,它(显然)执行ajax请求。我实现了一个函数来处理:

ajaxRequest = (url, params, callback) ->
    # implementation goes here
现在,假设我有一个从服务器获取数据的网格。在我的代码中,我必须执行以下操作:

userGrid.onMustFetch = ->
    ajaxRequest '/fetch/users', { surname: 'MacGyver' }, (data) ->
        # fill grid with data
class UserGrid {

    private AjaxService ajaxService;

    @Inject
    public UserGrid(AjaxService ajaxService) {
        this.ajaxService = ajaxService;
    }

    public void onMustFetch() {
        HashMap<String, String> params = new HashMap<String, String>();
        params.put("surname", "MacGyver");
        ajaxService.request("/fetch/users", params, new AjaxCallback(data) {
            // fill grid with data
        });
    }

}
这里到底有什么问题?如果我想测试onMustFetch的实现,我将无法这样做,因为在onMustFetch内部,正在调用一个依赖项,并且测试环境无法控制该依赖项

为了解决这个问题,我将依赖性注入到我想要测试的函数中。这意味着将onCustomFetch更改为:

现在,测试代码可以将ajaxRequest的模拟传递给onCustomFetch并成功地测试该行为

文德巴,对吗?错了!现在我有第二个问题,必须将正确的ajaxRequest实例绑定到正确的OnCustomFetch实例

在Java这样的语言中,我可以使用依赖注入框架来完成这项工作,我的代码如下所示:

userGrid.onMustFetch = ->
    ajaxRequest '/fetch/users', { surname: 'MacGyver' }, (data) ->
        # fill grid with data
class UserGrid {

    private AjaxService ajaxService;

    @Inject
    public UserGrid(AjaxService ajaxService) {
        this.ajaxService = ajaxService;
    }

    public void onMustFetch() {
        HashMap<String, String> params = new HashMap<String, String>();
        params.put("surname", "MacGyver");
        ajaxService.request("/fetch/users", params, new AjaxCallback(data) {
            // fill grid with data
        });
    }

}
class用户网格{
私人AjaxService AjaxService;
@注入
公共用户网格(AjaxService AjaxService){
this.ajaxService=ajaxService;
}
onMustFetch()上的公共void{
HashMap params=新的HashMap();
params.put(“姓氏”、“麦基弗”);
请求(“/fetch/users”,参数,新的AjaxCallback(数据){
//用数据填充网格
});
}
}
令人毛骨悚然,我知道。。。但实际上DI框架完成了所有的布线,所以至少这部分问题更容易解决

现在回到我们的web应用和Javascript。即使我成功地设法始终使用正确的ajaxRequest引用调用onCustomFetch(毕竟在本例中这并不难做到),也必须有一种更简单的方法。当我的代码增长时,依赖关系就会增加。我可以想象传递ajaxRequest的引用,但是当我有一个securityService、browserService、eventBusService等时会怎么样

现在这里真正的问题是:类似lisp的语言如何解决管理依赖关系的问题?
(在我看来,依赖关系必须在整个应用程序中不断传递,但我确信一定有更好的方法…

在Javascript中,我不知道为什么不能使用类似于任何OO语言的技术。一个非常基本的JS实现(对不起,我不知道Coffescript)

创建:

var userGrid = diController.create(UserGrid);

因此,
diController
执行与java依赖项注入器相同的操作。在java中,它可以使用反射来确定需要什么类型的对象。Javascript中没有太多的反映需要做,因此创建一个约定来告诉系统需要什么。在本例中,我使用了一个名为“dependencies”的数组,但您可以使用任何您喜欢的构造。

这通常是使用闭包/套用来完成的。您将依赖项作为参数传入。在JS中,您可以执行以下操作:

buildUserGrid = function(dependency){
    return {
        onMustFetch = function(){
            depenency.doSomething();
        },
        doSomethingElse = function(){
            dependency.doSomethingElse();
        }
    }
}

var userGrid = buildUserGrid(ajaxRequest);
userGrid.onMustFetch();

类似Lisp的语言彼此不同。它们有不同的对象系统,等等。这个问题实际上是关于Javascript的:如何在Javascript中实现Java设计模式(依赖项注入)。我正在删除非主题标记[clojure][lisp]和[scheme]。这与javascript无关。Javascript恰好是我所熟悉的表达问题的方式。我对lisp语言处理这个问题的方式很感兴趣,所以如果你能把标签放回去,我将不胜感激。请随意用一种对Lisp、Clojure或Scheme有意义的方式来重新表述这个问题。是的,我可以使用一种在OO中使用的技术。但我的问题和兴趣是函数式语言,特别是lisp语言,如何管理依赖关系。我知道在我的问题中这可能不够清楚,但是读一下我对这个问题的评论,你就会明白为什么。不过,谢谢……如果是那样的话,我认为最初的评论是非常相关的。或者,您是在问如何在没有全局或工厂概念的情况下管理依赖关系吗?你为什么要这么做?可用于创建此类结构的工具非常特定于语言。如果没有任何类型的全局构造,那么您已经回答了自己的问题,您将传递东西。事实上,到目前为止,我得到的选项是依赖注入、共享全局、工厂或传递东西。我试图找出在类似Lisp的语言中通常做什么。所以,也许你是对的,也许在我提出的背景下,我的问题没有其他答案。