AngularJS学习服务和工厂,工厂服务?

时间:2014-10-27 13:35:26

标签: javascript angularjs

在重构一个相当大的项目之前,我真的试图围绕角度的服务/工厂/提供商构造。

我已阅读很多关于服务与工厂的文档和文章,并认为我了解每个文档是如何创建的以及它们的作用。

然而,在尝试尝试的时候,我试图在工厂或两个工厂使用服务......

这非常有用:我现在明白我的“jsonService”中只有一个' (它是一个单身人士),所以这个简单的方法将无法工作......(我需要每个工厂都有一个单独的实例)

.service('jsonService', ['$http', function ($http) {
    var data= {'msg':'no data'};
    this.serviceData= data;
    this.get= function(url){
        $http.get(url).then(function (resp) {
            data= resp.data;
        }); 
    }
}])
.factory('fac1', ['jsonService', function(jsonService){
    jsonService.get('json/data1.json');
    return jsonService.serviceData;
}])
.factory('fac2', ['jsonService', function(jsonService){
    jsonService.get('json/data2.json');
    return jsonService;
}])

当我在控制器中使用工厂时:

myController.f1= fac1;
myController.f2= fac2.serviceData;

我可以看到 fac1 fac2 都返回相同的对象,它们都有 {msg:&#39;没有数据&#39;} < / em>,如果我改变一个,那么他们都会改变。

我的问题是:

即使我可以打破服务并看到 data = {msg:&#39;没有数据&#39;} 并看到它被设置为响应数据 - 为什么我看不到 fac1 fac2 的任何变化?

我能想到的是,某个地方必须有多个 var data ,有些东西不是单身&#39; ????

编辑:我现在尝试过:

this.serviceData= function(){return data;};

myController.f2= fac2.serviceData();  // this is always the 'no data' object
myController.f3= fac2.serviceData;

如果我(很久以后)打电话:

var something= myController.f3();

然后我得到了json数据......但myController.f2仍然是 {msg:&#39;没有数据&#39;} 为什么?

3 个答案:

答案 0 :(得分:1)

好的,在尝试了m.e.conroy的建议之后我终于明白了......

这个问题与angular无关,它是javascript传递对象的方式。 (见:Is JavaScript a pass-by-reference or pass-by-value language?

工厂传回原始 {msg:'无数据'} 对象的“复制参考”,并最终分配了服务:

data= resp.data;

替换了'数据',但工厂提供的引用仍然是旧对象。

现在,如果我这样做:

.service('jsonService', ['$http', function ($http) {
    var data= {'msg':'no data', 'result':null};
    this.serviceData= data;
    this.get= function(url){
        $http.get(url).then(function (resp) {
            data.result= resp.data;  // update properties of the data object
            data.msg='got data!';    // instead of replacing it
        }); 
    }
}])

......然后一切都有意义!

myController 中的变量在数据到达时会发生变化(因为我还没有'换出'数据对象)。

显然,我仍有问题,我的两个工厂都会返回同一个对象(我会看看Sacho对此的建议) - 但我想我已经学会了一些非常基本的东西。< / p>

答案 1 :(得分:0)

试试这个:

this.serviceData = function(){
    return data;
};

你也可能有种族的情况。在应用程序要求serviceData

时, $ http 可能尚未返回

答案 2 :(得分:0)

角度的“服务”和“工厂”之间的区别微乎其微 - 我建议只使用其中一个,并坚持使用它。从这一点开始,我将这些元素称为“服务”,即使我只使用angular.factory来声明它们。

对于您最终想要做的事情,有一个更简单的解决方案 - 只需从您的服务中返回承诺。

this.get= function(url){
    return $http.get(url)
}

然后在你的controller / directive /中,只需使用它:

jsonService.get(url).then(function success(response) {
    // do things with the response
})

但是您似乎想要使用服务来创建许多实例,所以这是一个人为的例子:

.factory('jsonService', jsonService)

jsonService.$inject = ['$http']
function jsonService($http) {
    return Fixed

    function Fixed(url) {
        this.url = url
        this.promise = null
        this.get = get.bind(this)

        function get() {
            // This caches the request so you only do it once, for example
            if (this.promise == null) {
                this.promise = $http.get(url)
            }
            return this.promise
        }
    }
}

然后在你的控制器中,你会做类似的事情:

var fixedOne = new jsonService('fixedOne')
fixedOne.get().then(...)