繁体   English   中英

使用John Papa的AngularJS样式指南,声明数据对象的正确方法是什么?

[英]Using John Papa's AngularJS style guide, what is the proper way to declare data objects?

假设我有一个AngularJS数据服务,它调用服务器并返回一个可以使用其他方法扩展的对象。 例如,假设以下函数是NerdDinner之类的AngularJS服务的一部分。

function getDinner(dinnerId) {
   return $http.get('api/dinner/' + dinnerId)
      .then(loadDinnerComplete)
      .catch(loadDinnerFailed);

   function loadDinnerComplete(response) {
      return new Dinner(response.data);
   }
}

一个地方定义晚餐课的最佳做法是什么? 这是一个单独的文件工厂吗? 我在NerdDinner服务中定义了吗? 或者我在GetDinner类中定义它(假设这是唯一可以创建晚餐的方法)?

我没有找到任何具体的参考在风格指南中创建对象,所以请原谅我,如果它被覆盖,我只是错过了它。

编辑我最终决定接受Jeroen的答案,因为它最符合我对一个相当简单的用例的需求。 然而, 丹尼尔的回答是纯金,不应该被忽视。 如果我选择使用简单的CRUD或其他基于服务器的操作来扩展DTO的功能,那么$ resource是一种很好的方法。

在John Papa的风格指南(afaik)中没有明确提到商业实体(如晚餐)的位置。

如果你想走这条路(使用商业实体并在那里放置逻辑),我应该为每个实体提供自己的工厂:

(function() {
  'use strict';

  angular
    .module('myDinner')
    .factory('Dinner', DinnerFactory);

  function DinnerFactory() {

    Dinner.prototype.eat = eat;
    Dinner.prototype.cancel = cancel;

    return Dinner;

    // Constructor

    function Dinner (data) {
        // this is just an example:
        this.time = data.time;
        this.location = data.location;
    }

    // Methods

    function eat() {
      // ...
    }

    function cancel() {
      // ...
    }

  }

})();

然后,您可以将它们注入您的控制器或其他服务对象,只需使用Dinner ,然后使用new Dinner(data)创建一个新的Dinner对象。

您也可以使用服务,但John Papa不鼓励服务,因为它们与工厂太相似。

国际海事组织你正在做的事情已经完成了$resource和恢复。 您正在谈论“定义数据对象”(或典型用语中的模型)。 也就是说,根据John Papa关于单一问题的建议,将每个“数据对象”定义为自己的工厂就是这样做的方法。

John Papa在工厂部分讨论了这个问题

如果你想手动解决这个问题,IMO你可以定义你的模型,并在每个模型上附加代表各种crud操作的方法。 这是模式$resource和restangular(有点)采取。

//Dinner model as angular factory, each of these methods returns a promise

function Dinner($http) {
    return {
        create: function(route, body) { /** http.post */ },
        get: function(route) { /** http.get */ },
        update: function(route, body) { /** http.put */ },
        destroy: function(route) { /** http.delete */ }
    };
}

现在您的Dinner模型内置了方便的crud方法,您可以这样做

var dinner = new Dinner;
dinner.get("/api/dinner/1").then() //get dinner with id of 1
dinner.update("/api/dinner/1", {name: "burger"}).then() //update dinner with id of 1

编辑:

因此,如果您想创建一个与检索数据无关的对象,您应该创建另一个需要您的模型的工厂。 这将您的数据检索与数据操作分离。 在OP原始示例中,数据检索和操作紧密耦合。

function Meal(dinner) {
    //this.meal is the specified dinner
    this.meal = new Dinner().get("/api/dinner" + dinner);

    //some random build-in data manipulation methods
    return {
        getCalories: function() { return this.meal * 400; },
        getPrice: function() { return (this.meal * 100) + "$"; }
    };
}

现在您已将数据操作分离为单独的对象,您可以执行类似的操作(这是一个同步示例)

var mcdonalds = new Meal(/** specify which dinner */)
mcdonalds.getPrice() //$4.56
mcdonalds.getCalores() //9999

我个人使用了ServicesFactories来创建对象。 然而,从John Papa的风格指南:

使用new关键字实例化服务,将this用于公共方法和变量。 由于这些与工厂非常相似,因此请使用工厂来保持一致性。

SRP之后 ,您应该将它放在新ServiceFactory而不是另一个ServiceFactory

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM