JavaScript揭示模块模式公共变量不更新

时间:2014-02-13 21:45:12

标签: javascript angularjs revealing-module-pattern

我正在使用带有Revealing Module模式的Angular服务。该服务在内部从Web服务中提取字符串资源,并通过“Strings”公共变量使其可用。我必须初始化私有'strings'变量,因为它在服务调用之前被引用。

我从服务中获取正确的字符串数据并将其复制到私有的“字符串”变量。但是,当客户引用公共“字符串”时,它仍然保留其原始值。

知道我做错了什么,或者如何公开'Strings'来更新?

'use strict';

io1App.factory('Resources', ['$rootScope', 'DataService', '$q',
function ($rootScope, DataService, $q) {

   var urlBase = '/api/sfc/resource';

    // Need to pre-define 'ERROR_HEADER', since it is referenced in Index.html...before we have a chance to download it from the server.
   var strings = {
       'ERROR_HEADER': 'Error!'
   };

    var getStringResources = function (locale) {

        var url = urlBase + '/' + locale;

        var deferred = $q.defer();

        var promise = DataService.GetMethod(url);

        // Note that DataService.GetMethod(...) is returning a $q promise
        promise.then(function (data) {
            strings = data;
            deferred.resolve();
        },
        function (err) {
            deferred.reject(err);
        });

        return deferred.promise;
    };

    return {
        Strings: strings,
        GetStringResources: getStringResources
    }
}]);

服务调用将返回的数据设置为私有的“字符串”变量

promise.then(function (data) {
            strings = data;
            deferred.resolve();
        },

私人'字符串'现在显示以下内容(通过Chrome开发者工具):

strings = {
       'ERROR_HEADER': 'Error!'
       'INVALID_PROCESS_ORDER': 'Process Order [%d] could not be entered because it does not belong to Manfacturing Order [%d]',
       'DUPLICATE_PROCESS_ORDER': 'Process Order [%d] already entered.',
       'USER_NOT_ITAR': 'Manufacturing order [%d] is ITAR, and you are not ITAR approved.  You cannot proceed with this order.  Please contact your supervisor.'
   };

然而,当Angular控制器中引用公共'Strings'时,'Strings'仍然引用私有'字符串'的原始值。

Resource.Strings:

{
   'ERROR_HEADER': 'Error!'
};

有什么建议吗?

2 个答案:

答案 0 :(得分:0)

您正在使用strings完全替换data变量。它们是不同的对象并具有不同的引用,因此任何引用前一个strings对象的客户端代码都不会看到更改。

您可以扩充现有的strings对象,而不是替换。

promise.then(function (data) {
    // Merge properties into `strings`
    // You could also use any other "extension" technique, e.g. _.extend()
    for (var k in data) {
        if (data.hasOwnProperty(k)) {
            strings[k] = data[k];
        }
    }
    deferred.resolve();
},

答案 1 :(得分:0)

从工厂方法返回的JavaScript对象永远不会使用新的字符串对象进行更新。您需要保留对它的引用才能更新“公共视图”:

service = {
    Strings: strings,
    GetStringResources: getStringResources
};
return service;

然后更新您的.then回调以更新私有变量以及公共服务对象:

.then(function(data) {
    strings = service.strings = data;
    deferred.resolve(data); // don't need to resolve this with the strings, but why not?
}, function error(){...});

但是,由于您不再真正拥有“私有数据”(仅对公共变量的私有引用),您根本不需要拥有私有字符串变量:

io1App.factory('Resources', ['$rootScope', 'DataService', '$q',
function ($rootScope, DataService, $q) {

    var urlBase = '/api/sfc/resource';

    var service = {
        // Need to pre-define 'ERROR_HEADER', since it is referenced in Index.html...before we have a chance to download it from the server.
        Strings: { 'ERROR_HEADER': 'Error!' },
        GetStringResources: function (locale) {
            var url = urlBase + '/' + locale;
            var deferred = $q.defer();
            var promise = DataService.GetMethod(url);

            // Note that DataService.GetMethod(...) is returning a $q promise
            promise.then(function (data) {
                service.strings = data;
                deferred.resolve(data); // don't need to resolve this with the strings, but why not?
            },
        function (err) {
            deferred.reject(err);
        });

        return deferred.promise;
    };
    return service;
}]);