-1

我正在尝试设置一些基本场景并使用 LoopBack 来找出它的实际灵活性和可用性水平。

其中之一是在处理来自数据库(例如 MySQL)的源数据期间,必须修改结果 JSON 对象中某些属性的值。

我正在使用以下版本:

strong-cli v2.5.5 (node v0.10.29) node-inspector v0.7.4 strong-build v0.1.0 strong-cluster-control v0.4.0 strong-registry v1.1.0 strong-supervisor v0.2.3 (strong-agent v0. 4.9, strong-cluster-control v0.4.0) loopback-datasource-juggler v1.6.2 loopback-connector-mysql v1.4.1

我尝试了所有方法,但看起来“getter”方法是以我不理解的方式应用的,或者存在错误。

为了描述这个问题,我使用了一个简单的表“city”(在 MySQL db 中):

CREATE TABLE `city` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `countryId` bigint(20) NOT NULL,
  `name` varchar(100) NOT NULL,
  `comment` varchar(255) DEFAULT NULL,
  `enabled` char(1) NOT NULL DEFAULT 'Y',
  PRIMARY KEY (`id`),
  UNIQUE KEY `id_UNIQUE` (`id`)
)

并填写了一些简单的数据。

为了在 LoopBack 中定义模型,我使用了位于“models”目录中的文件“city.js”:

"use strict";

var loopback = require('loopback');
var app = require('../app.js');

var properties = {
    id: {type: "number", id: true},
    countryId: {type: "number"},
    name: {type: "string"},
    comment: {type: "string"},
    enabled: {type: "string"}
};

var options = {
    acls: [
        {
            accessType: "*",
            permission: "ALLOW",
            principalType: "ROLE",
            principalId: "$everyone"
        }
    ]
};

var City = app.model("city", {
    properties: properties, 
    options: options,
    public: true,
    dataSource: "mysql",
    plural: "cities"
});

City.getter["enabled"] = function(v) {
    console.log("Getter is called: ", v);
    return 'Q'
};

如您所见,“getter”方法是使用“City”对象在“city”模型上定义的。

当我尝试运行 LoopBack 然后通过 StrongLoop API Explorer 发送请求时:

http://localhost:3000/api/cities/1

控制台看起来像(包含 DEBUG=loopback:connector:* 的信息):

supervisor running without clustering (unsupervised)
loopback:connector:mysql Settings: {"connector":"loopback-connector-mysql","host":...
connect.multipart() will be removed in connect 3.0
visit https://github.com/senchalabs/connect/wiki/Connect-3.0 for alternatives
connect.limit() will be removed in connect 3.0
Getter is called:  undefined
Getter is called:  undefined
2014-07-12T12:26:41.978Z pid:12180 worker:supervisor INFO strong-agent not profiling, ...
2014-07-12T12:26:41.981Z pid:12180 worker:supervisor Generate configuration with:
2014-07-12T12:26:41.983Z pid:12180 worker:supervisor     npm install -g strong-cli
2014-07-12T12:26:41.983Z pid:12180 worker:supervisor     slc strongops
2014-07-12T12:26:41.983Z pid:12180 worker:supervisor See http://docs.strongloop.com/...
Browse your REST API at ...
LoopBack server listening @ ...
Getter is called:  undefined
  loopback:connector:mysql SQL: SELECT * FROM `city` WHERE `id` = 1 LIMIT 1 +8s
  loopback:connector:mysql Data:  +9ms [ { id: 1,
    countryId: 1,
    name: 'Brno',
    comment: 'The second largest city of its country',
    enabled: 'Y' } ]
Getter is called:  undefined
GET /api/cities/1 304 44ms

结果如下:

{
  "id": 1,
  "countryId": 1,
  "name": "Brno",
  "comment": "The second largest city of its country",
  "enabled": "Q"
}

如您所见,“启用”属性最终由“getter”方法更改,但是:

  • 在 LoopBack 初始化期间,“getter”方法也被调用了 2 次
  • 在查询 MySQL 数据库之前,“getter”方法也被调用了 1x
  • 'getter' 方法中的 console.log(v) 总是返回 'undefined'

loopback-datasource-juggler 中“model-builder.js”的源代码(第 364 行)

Object.defineProperty(ModelClass.prototype, propertyName, {
  get: function () {
    if (ModelClass.getter[propertyName]) {
      return ModelClass.getter[propertyName].call(this); // Try getter first
    } else {
      return this.__data && this.__data[propertyName]; // Try __data
    }
  },

是一个解释为什么。'call' 方法只有一个参数(this)代表被调用函数中的 'this' 对象,并且没有第二个参数代表被调用函数中的参数 'v'(与 Raymond Feng 关于How我要创建 getter 和 setter 覆盖吗?)。

问题还在于“getter”方法中的“this”始终表示一个包含模型所有属性的对象:

City.getter["enabled"] = function(v) {
    console.log("Getter is called: ", this);
    return 'Q'
};

然后来自控制台的消息:

Getter is called: { id: 1, countryId: 1, name: 'Brno', comment: 'The second largest city of its country', enabled: 'Y' }

你能解释一下“getter”方法的当前实现的想法吗?

非常感谢。

米洛斯·拉皮斯 MLC

更新

非常感谢雷蒙德的回答。

一开始我以为是这样,但是当我使用类似的东西时:

City.getter["enabled"] = function() {
    return this.enabled + "x"
};

当我请求时,节点立即崩溃:

localhost:3000/api/cities/1

出现错误: RangeError:超出最大调用堆栈大小

这就是为什么我认为您的实现有点不同。有什么不对?

我究竟应该使用什么来将“x”添加到从 db 检索到的实际值中?

谢谢。

米洛斯·拉皮斯 MLC

4

2 回答 2

1

JavaScript getter 函数采用以下格式:

function() {
  // this is the object instance owning the property
}

请注意,getter 函数不接受任何参数,接收者是拥有该属性的对象实例。例如:

myModelInstance.myProperty 将调用 getter 函数并将此设置为 myModelInstance。在https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Working_with_Objects中查看更多信息。

于 2014-07-13T04:54:07.767 回答
1

在您的示例代码中,您递归地调用您定义的 getter。

City.getter["enabled"] = function() {
  // this.enabled calls City.getter["enabled"]
  return this.enabled + "x"
};

从 DB 中检索的值存储在__data属性中。这是更正后的 getter 函数:

City.getter["enabled"] = function() {
  return this.__data.enabled + "x"
};
于 2014-08-22T07:28:31.240 回答