简体   繁体   English

过滤ES6类的属性

[英]Filter properties from ES6 class

I have a Dto that I want to enable the service layer to filter: The method selectFields takes an array of field names that should be returned, the other properties will be removed. 我有一个Dto,我想要启用服务层过滤:方法selectFields采用应返回的字段名称数组,其他属性将被删除。
What is a short way to enumerate the properties on the class so I can loop through them and set the filtered ones to null? 什么是枚举类的属性的简短方法,以便我可以遍历它们并将过滤后的属性设置为null?
In the BaseDto I take care of cleaning falsy values (well I need the same function here too as a matter of fact). 在BaseDto我负责清理假值(我在这里也需要相同的功能)。

class UserServiceDto extends BaseDto {
  constructor(userDto) {
    super();
    this.fbUserId = userDto.fbUserId;
    this.fbFirstName = userDto.fbFirstName;
    this.fbLastName = userDto.fbLastName;
    this.gender = userDto.gender;
    this.birthdate = userDto.birthdate;
    this.aboutMe = userDto.aboutMe;
    this.deviceToken = userDto.deviceToken;
    this.refreshToken = userDto.refreshToken;
    this.updatedAt = userDto.updatedAt;
    this.createdAt = userDto.createdAt;
  }

  selectFields(fields) {
    // --> what's your take? 
  }

  toJson() {
    return super.toJson();
  }
}

Edit: 编辑:
The service layer receives a dto from repository layer including all database fields. 服务层从存储库层接收dto,包括所有数据库字段。 The ServiceLayerDto aims at filtering out fields that are not required by the web api (or should not be exposed as a security measure eg PK field, isDeleted, etc). ServiceLayerDto旨在过滤掉web api不需要的字段(或者不应作为安全措施公开,例如PK字段,isDeleted等)。 So the result would I'm looking at the end of a service method for would look something like: 所以结果我会看到服务方法的结尾看起来像:

return new UserServiceDto(userDto)
  .selectFields('fbUserId', 'fbFirstName', 'fbLastName', 'birthdate', 'aboutMe', 'updatedAt', 'createdAt')
  .toJson();

The return value would be a plain json object that the web layer (controller) sends back to the http client. 返回值将是web层(控制器)发送回http客户端的普通json对象。

If you are ok with spread operator, you may try following approach: 如果您对扩展运算符没问题,可以尝试以下方法:

class UserServiceDto {
  constructor() {
    this.a = 1;
    this.b = 2;
    this.c = 3;
  }
  selectFields(...fields) {
    const result = {};
    fields.forEach(key => result[key] = this[key]);
    return result;
  }
}

new UserServiceDto().selectFields('a', 'c'); // {a: 1, c: 3}

Looking to super.toJson() call, I think that it would not work due to the result of my selectFields() call would not be an instance of UserServiceDto class. 期待super.toJson()调用,我认为由于我的selectFields()调用的结果不会是UserServiceDto类的实例,它将无法工作。 There are some possible ways from this point I see: 从这一点来看,有一些可能的方法我看到:

  • instantiate new UserServiceDto object inside selectFields() body, remove all fields that not listed in the ...fields array (javascript delete is okey) and return it; selectFields()体内实例化新的UserServiceDto对象,删除...fields数组中列出的所有字段(javascript delete is okey)并返回它;
  • play with UserServiceDto constructor params to save positive logic on selectFields() , and pass to constructor only that props that need to be set up; 使用UserServiceDto构造函数params来保存selectFields()上的正逻辑,并仅传递给需要设置的props的构造函数; in this case instantiating a temporary object will not require properties removing; 在这种情况下,实例化临时对象不需要删除属性;
  • change the signature of toJson method, or better add a new signature, which would allow to pass fields array and then put current selectFields logic inside toJson method (and remove selectFields method at all): new UserServiceDto().toJson('a', 'c') ... 更改toJson方法的签名,或者更好地添加一个新签名,这将允许传递fields数组,然后将当前selectFields逻辑放在toJson方法中(并删除selectFields方法): new UserServiceDto().toJson('a', 'c') ......

Purely for info, I ultimately changed my app architecture. 纯粹为了信息,我最终改变了我的应用程序架构。

The repository returns a Dto to the service layer (dto being mapped directly from the sql queries). 存储库将Dto返回到服务层(dto直接从sql查询映射)。
The service builds a static View based on the Dto and returns it to the web layer (represented by a plain json object). 该服务基于Dto构建静态视图并将其返回到Web层(由普通json对象表示)。

In my directory structure, I have: 在我的目录结构中,我有:

- service
-- views
--- index.js
--- UserInfo.js

The view is a simple filter. 视图是一个简单的过滤器。 Eg UserInfoView: 例如UserInfoView:

exports.build = ({ fbUserId, fbFirstName, fbLastName, gender, birthdate, aboutMe, updatedAt, createdAt }) => {
  return {
    fbUserId,
    fbFirstName,
    fbLastName,
    gender,
    birthdate,
    aboutMe,
    updatedAt,
    createdAt,
  };
};

Using the view, eg UserInfoView in the service looks like this: 使用该视图,例如服务中的UserInfoView如下所示:

const Views = require('../service/views');

exports.findActiveByUserId = async (pUserId) => {
  const userDto = await UserRepository.findActiveByUserId(pUserId);
  if (!userDto) {
    throw new ServiceError(Err.USER_NOT_FOUND, Err.USER_NOT_FOUND_MSG);
  }
  return Views.UserInfo.build(userDto.toJson());
};

I think that this is much more descriptive compared to my initial take on the problem. 我认为与我最初对这个问题的看法相比,这更具描述性。 Also, it keeps the data objects plain (no additional methods required). 此外,它使数据对象保持平原(无需其他方法)。
It is unfortunate that I can't require receiving an type (View) in the web layer, I might be able to solve that problem with Typescript later on. 遗憾的是,我不能要求在Web层中接收类型(View),我可能稍后可以使用Typescript解决该问题。

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

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