NodeJS Meteor中的全局变量

lsmepo6l  于 2023-06-22  发布在  Node.js
关注(0)|答案(5)|浏览(125)

我有

var Schemas = {};

Meteor.isClient && Template.registerHelper("Schemas", Schemas);

Schemas.Person = new SimpleSchema({
  fullName: {
    type: String,
    index: 1,
    optional: true,
  },
  email: {
    type: String,
    optional: true
  },
  address: {
    type: String,
    optional: true
  },
  isActive: {
    type: Boolean,
  },
  age: {
    type: Number,
    optional: true
  }
});

在一个文件中

var Collections = {};

Meteor.isClient && Template.registerHelper("Collections", Collections);

Persons = Collections.Persons = new Mongo.Collection("Persons");
Persons.attachSchema(Schemas.Person);

在另一个文件中。
我得到错误ReferenceError: Schemas is not defined。很明显,我必须在collections.js文件中定义Schemas,而不是将它们分开。但是Meteor如何处理单独文件中的代码呢?我可以访问一些对象和变量,而其他的是不可访问的。

wgeznvg7

wgeznvg71#

当你以经典的JavaScript方式定义一个变量时:

var someVar = 'someValue';

.js文件的根目录下,Meteor使用IIFE将其限制到该文件。
如果你想定义一个全局变量,只要不写var,给出:

someVar = 'someValue';

默认情况下,这将在所有应用程序中定义一个变量,尽管您可以通过在特定的可识别文件夹(例如clientserver文件夹)中编写该声明来限制它。
然而,这个变量不会首先被绝对定义。它将在Meteor运行定义它的实际代码时定义。因此,这可能不是最佳实践,因为你将与加载顺序作斗争,它将使你的代码依赖于Meteor如何加载文件:你把文件放在哪个文件夹文件名如果你稍微触及你的架构,你的代码很容易出现混乱的错误。
正如我在another closely related post中所建议的,你应该直接去买一个包!

tvz2xvvm

tvz2xvvm2#

Meteor中使用var关键字声明的变量的作用域是声明它们的文件。
如果你想创建一个全局变量,请这样做

Schemas = {}
fkvaft9z

fkvaft9z3#

ReferenceError是一个节点错误。Meteor是Node之上的一个框架。
Node有一个全局作用域(也就是Node的global变量)。如果尝试访问未定义的全局变量,Node(不是Meteor)会抛出此错误。
浏览器也有一个名为window的全局作用域,当访问未定义的变量时不会抛出ReferenceErrors。
这里有一个我喜欢的向类添加功能的模式(非常像流星):

/lib/Helpers.js      <-- Helpers for everyone (node+browser)
/server/Helpers.js   <-- Server helpers (node)
/client/Helpers.js   <-- Client helpers (browser)

考虑以下实现:

// /lib/Helpers.js
Helpers = {/* functions */};  // Assigned to window.Helpers and global.Helpers

// /server/Helpers.js
Helpers = _.extend(Helpers, {/*more functions*/}

// /client/Helpers.js
Helpers = _.extend(Helpers, {/*more functions*/}

这是一个简单的例子。如果我不想担心装货顺序呢?为什么不在/lib/Helpers.js中使用_.extend()?

// /lib/Helpers.js
// Helpers = {/* functions */};                  // Overwrites...
Helpers = _.extend(Helpers, {/* functions */});  // ReferenceError

因为如果没有定义Helpers,你会从Node得到一个ReferenceError--特别是作为参数使用的“Helpers”。(节点知道将Helpers分配为global.Helpers)。

这里有两种方法来“修复”这个问题:

1)将助手分配给某个对象

// /lib/Helpers.js
// Helpers = Helpers || {}    // would be another ReferenceError
if (typeof Helpers === 'undefined') Helpers = {};
Helpers = _.extend(Helpers, {/* functions */});

2)使用全局

// /lib/Helpers.js
Helpers = _.extend(global.Helpers, {/* functions */});  // works in node, but...

两个都很烂

1)的语法很可怕。
2)在node中工作,但在浏览器中没有全局。所以它没有达到它的目的。
所以我放弃了,回到了第一次在lib中覆盖它的方法,并在任何内容被覆盖时查找运行时错误。
如果你有一个方便的跨浏览器语法,请注解:-)var something = something|| {} something.blah = foo;
这是另一个JS shorthand tips

nhjlsmyf

nhjlsmyf4#

会话变量是全局的,可以在不同的文件/函数中轻松访问。setPersistent用于在所有文件中持久地设置变量名。当应用程序太大时,可能会限制使用会话变量,因为它们不会被删除(因此可能会导致内存泄漏),并且可能会在控制台中给予错误(如果未定义)。链接到文档:https://docs.meteor.com/api/session.html

vbkedwbf

vbkedwbf5#

添加类型检查:
看起来使用globalThis有助于VS Code TS检查。所以我没有

MyCollection = new Mongo.Collection('col')

我写作

globalThis.MyCollection = new Mongo.Collection('col')

最终我会将这个庞大的项目转换为ESM,但现在,至少我摆脱了所有的VS代码引用错误。

相关问题