创建一个像OO类一样的角度服务

时间:2016-05-22 16:19:53

标签: javascript angularjs

我有一个回答“Widgets”的网络服务,每个都有一大堆简单的对象,“部分”,需要单独提取。我希望将此作为一个角度服务公开,它提取小部件 - 以及其中一些部分 - 并将结果缓存在localStorage中,但我遇到了问题(在代码中注明,然后在下面)...

angular.module('myApp').service('myWidgetService', function ($q, requestService, localStorageService, _) {

    // start everything off by fetching the Widgets, saving locally
    this.refresh = function() {
        var self = this;
        return requestService.request('GET', '/api/widget/', true).then(function(result) {
            self.setCloudArray(result);
            // I want callers to use "Widget instances" defined below
            return _.map(result, function(cloudItem) { return new Widget(cloudItem); });
        });
    };

    // get and set persistent widget array
    this.cloudArray = function() {
        return localStorageService.get('cloudArray');
    };

    this.setCloudArray = function(cloudArray) {
        localStorageService.set('cloudArray', cloudArray);
    };

    // I want this "Widget instance" to provide methods related to a single widget
    var Widget = function(cloudItem) {
        this.cloudItem = cloudItem;  // PROBLEM A:  (this indirection hurts me later)
    };

    // get the parts, but only if they haven't been fetched already
    // if they've been fetched, return the cached copy
    Widget.prototype.parts = function() {
        var self = this.cloudItem;  // weirdness due to PROBLEM A
        if (self.parts) { return $q.when(self.parts); }
        var route = '/api/widget/' + self._id + '/parts';
        return requestService.request('GET', route, true).then(function(result) {
            self.parts = result;  // PROBLEM B: how to persist?
            return result;
        });
    };

    Widget.prototype.partWithId = function(id) {
        return _.find(this.cloudItem.parts, function(part) { return part._id === id; });
    };

});

我在代码中标记了我遇到的两个问题。

问题A:我真的不想在我的Widget中添加一个cloudItem属性。在窗口小部件方法中,我想对对象的this.foo属性说foo之类的内容,但我不得不说this.cloudItem.foo

问题B:更大的问题是对小部件的调用是昂贵的,我想缓存结果。但是本地存储知道的是我的实例“cloudItem”所属的对象数组。我不知道在我的widget对象中保存的优雅方法。

我在类级别编写了一个不太优雅的方法来更新本地存储:

this.saveWidget = function(updatedWidget) {
    var cloudArray = this.cloudArray();
    var currentItem = _.find(cloudArray, function(i) { return i._id === updatedWidget._id; });
    var index = cloudArray.indexOf(currentItem);
    cloudArray[index] = updatedWidget;
    this.setCloudArray(cloudArray);
};
取出零件后我打电话给我。这很有效,但是虽然我对JS和Web开发没有太多经验,但我知道我已经把自己挖到了一个洞里。我已经阅读了很多关于服务和JS对象的东西,但很明显我错过了一些重要的东西。

如何避免我的Widget对象中的额外间接,并为其提供更直接,更OO的方式将自己保存到本地存储?

提前感谢您的帮助。

1 个答案:

答案 0 :(得分:0)

我学到了两件帮助我解决这个问题的事情:angular.extend()解决了我的第一个问题......

var Widget = function(cloudItem) {
    angular.extend(this, cloudItem);
    // replaces
    // this.cloudItem = cloudItem;  // PROBLEM A:  (this indirection hurts me later)
};

感谢extend()(以及返回'this'的隐藏魔法),我不需要'cloudItem'属性。

在我的第二个问题中,我失去了试图在对象级别保存状态。我想我必须忍受节约发生在班级的事实。

我使用对象级保存方法改进了一些东西(并且保留了索引对象而不是数组,这得益于@charlietfl的建议)

// replaces the awkward: this.saveWidget = function(updatedWidget) I had before
Widget.prototype.save = function() {
    var cloudArray = localStorageService.get('cloudArray');
    // really a cloud object, thanks to suggestion by @charlietfl
    cloudArray[this._id] = this;
    localStorageService.set('cloudArray', cloudArray);
};

至少我可以假装save()对我有意义。实例上的这个方法隐藏了(丑陋的,imo)事实,即在类级别上保存真的很糟糕。

Javascript很奇怪。