【问题标题】:Duplicated constants between Javascript and server-side codeJavascript 和服务器端代码之间的重复常量
【发布时间】:2014-04-22 18:46:02
【问题描述】:

在我的项目中,我的 JavaScript 代码中定义了一些与服务器上相同的变量(用不同的语言编写)。我有 cmets,当一侧改变时,另一侧也应该改变。这感觉像是共享这些变量的笨拙方式。

是否有在 JavaScript 脚本和我的网站后端之间共享变量的标准方法?

我想到的一些选项:

  1. 如果幸运并且两种语言的语法兼容,请使用共享常量源文件。
  2. 作为构建过程的一部分,基于另一种语言动态生成其中一种语言的常量文件。
  3. 通过模板语言生成所有 JavaScript。
  4. 将共享常量内嵌在 HTML 中,而不是将它们放在 JavaScript 文件中。

【问题讨论】:

  • 嗯,这样的工作会使用JavaScript framework 帮助吗?
  • 这不是真正的变量传递,它都是静态编译的,只是使用在两个项目中重复的变量。
  • 服务器端语言是什么?
  • Python,但我想同样的问题可能适用于任何语言。
  • 我会投票给#2。使用 python,这似乎并不难:将常量保存在一个类中,并在构建时(或部署时),将其内容 json 化为一个读取 var constants = {jsonified-constant-definitions-here};.js 文件,该文件将从加载当前 JS 的相同 html。

标签: javascript web


【解决方案1】:

我假设您追求的是单页应用程序。您可以将后端更改为 restful,并且每当需要更改某些内容时,您的 Javascript 都可以自行更新并通知后端。

看看AngularJS 等流行的javascript 框架,看看单页应用程序是如何开发的。前几个教程应该可以帮助您学习。

不,您不会直接共享变量。您将分享变量包含的值。当一个改变时,你会告诉你的应用程序更新另一个。

例如,假设您有以 JSON 格式输出用户的后端。

{
    "users": [
        {
            "firstName": "John",
            "lastName": "Doe"
        },
        {
            "firstName": "Anna",
            "lastName": "Smith"
        },
        {
            "firstName": "Peter",
            "lastName": "Jones"
        }
    ]
}

您将首先在 javascript 变量上初始化此信息。然后,每次用户被删除时(比如说被删除),您都需要从这个变量中删除用户并通知后端,这样他们就会同步。

我想给你更多关于它的信息,但我相信AngularJS 的第一个教程会让你明白很多事情。

【讨论】:

  • 这不回答 OP。 OP正在询问诸如“用户”之类的常量。如果后端决定将常量更改为“客户”,那么前端也必须使用“客户”。 JSON 中的这些键应该是某个文件中的常量,例如 const USER_KEY = 'users'。 OP 希望为此类常量提供一个文件,供后端和前端用于这些常量。
【解决方案2】:

我编写了一个名为 Reconstant 的 Python 工具来解决这个确切的问题。

这是一个示例输入文件test.yaml

constants:
- name: SOME_CONSTANT
  value: "this is a constant string"
- name: OTHER_CONSTANT
  value: 42

enums:
- name: SomeEnum
  values:
    - A
    - B
    - C
- name: OtherEnum
  values:
    - FOO
    - BAR

outputs:
  python:
    path: autogenerated_constants.py
  javascript:
    path: autogenerated_constants.js
  c:
    path: autogenerated_constants.h

现在您运行reconstant test.yaml 并生成以下输出文件:

autogenerated_constants.py
# autogenerated by reconstant - do not edit!
from enum import Enum

# constants
SOME_CONSTANT = "this is a constant string"
OTHER_CONSTANT = 42

# enums
class SomeEnum(Enum):
    A = 0
    B = 1
    C = 2

class OtherEnum(Enum):
    FOO = 0
    BAR = 1
autogenerated_constants.js
// autogenerated by reconstant - do not edit!

// constants
export const SOME_CONSTANT = "this is a constant string"
export const OTHER_CONSTANT = 42

// enums
export const SomeEnum = {
    A : 0,
    B : 1,
    C : 2,
}
export const OtherEnum = {
    FOO : 0,
    BAR : 1,
}
autogenerated_constants.h
// autogenerated by reconstant - do not edit!
#ifndef AUTOGENERATED_CONSTANTS_H
#define AUTOGENERATED_CONSTANTS_H

// constants
const char* SOME_CONSTANT = "this is a constant string";
const int OTHER_CONSTANT = 42;

// enums
typedef enum { A, B, C } SomeEnum;
typedef enum { FOO, BAR } OtherEnum;

#endif /* AUTOGENERATED_CONSTANTS_H */

这还不支持您提到的所有语言,但很容易添加对新语言的支持。上面显示的 Python 输出用 9 行代码实现,而 C 输出(最复杂)用 30 行代码实现。

【讨论】:

    【解决方案3】:

    option1 环境变量

    这取决于您的确切设置,但我会为这些常量使用环境变量,因为大多数语言和构建工具已经支持它。

    然后有一个 .env 文件,该文件从我两个项目的公共位置提取。

    option2 配置 api 端点

    另一种选择是让 api 端点为这些常量提供服务,并在构建时甚至在运行时将它们用于前端,具体取决于您的用例的具体情况

    【讨论】:

      【解决方案4】:

      集成测试是解决这个问题的好工具。

      创建一个测试套件,它会访问您的 API,并将返回的对象和变量与 JavaScript 中定义的对象/变量进行比较。您可以使用一些反射魔法创建此 API 端点并包含元数据以简化此比较或比较其他信息。

      然后让您的集成测试套件在持续集成服务器上运行,可能由 JS 或 API/服务器端的提交触发,并自动通知您测试失败。

      【讨论】:

        猜你喜欢
        • 2011-02-22
        • 1970-01-01
        • 2011-04-26
        • 2021-04-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-09-02
        • 1970-01-01
        相关资源
        最近更新 更多