Meteor API
Meteor 全局对象包含许多用于处理实用程序、网络等的函数和属性。
核心 API
在服务器上,该函数将在服务器进程完成启动后立即运行。在客户端上,该函数将在 DOM 准备好后立即运行。包装在 Meteor.startup
中的代码始终在所有应用程序文件加载后运行,因此如果您想访问其他文件中的共享变量,则应在此处放置代码。
startup
回调按调用 Meteor.startup
的顺序调用。
在客户端上,来自包的 startup
回调将首先被调用,然后是 <body>
模板来自您的 .html
文件,然后是您的应用程序代码。
import { Meteor } from "meteor/meteor";
import { LinksCollection } from "/imports/api/links";
Meteor.startup(async () => {
// If the Links collection is empty, add some data.
if ((await LinksCollection.find().countAsync()) === 0) {
await LinksCollection.insertAsync({
title: "Do the Tutorial",
url: "https://www.meteor.js.cn/tutorials/react/creating-an-app",
});
}
});
import React from "react";
import { createRoot } from "react-dom/client";
import { Meteor } from "meteor/meteor";
import { App } from "/imports/ui/App";
// Setup react root
Meteor.startup(() => {
const container = document.getElementById("react-target");
const root = createRoot(container);
root.render(<App />);
});
Meteor.promisify
摘要
获取一个具有回调参数作为最后一个参数的函数并将其变成 Promise。一种选择是使用节点实用程序 utils.promisify,但它在浏览器上不起作用。
参数
源代码名称 | 类型 | 描述 | 必需 |
---|---|---|---|
fn | 函数 | ---- | 是 |
context | 对象 | ---- | 否 |
errorFirst | 布尔值 | 如果回调遵循 errorFirst 样式,则默认为 true | 否 |
import { Meteor } from "meteor/meteor";
/** @returns function */
const result = Meteor.promisify(
() => {},
context, // this param is optional
false, // this param is optional
);
Meteor.defer
摘要
延迟函数的执行以在后台异步运行(类似于 Meteor.setTimeout(func, 0)
。
参数
源代码名称 | 类型 | 描述 | 必需 |
---|---|---|---|
func | 函数 | 要运行的函数 | 是 |
import { Meteor } from "meteor/meteor";
Meteor.defer(
() => {}
);
Meteor.absoluteUrl
摘要
生成指向应用程序的绝对 URL。服务器从 ROOT_URL
环境变量读取以确定它在哪里运行。对于部署到 Galaxy 的应用程序,这会自动处理,但在使用 meteor build
时必须提供。
参数
源代码名称 | 类型 | 描述 | 必需 |
---|---|---|---|
path | 字符串 | 要附加到根 URL 的路径。不要包含前导“ | 否 |
options | 对象 | 否 |
import { Meteor } from "meteor/meteor";
Meteor.absoluteUrl(
"path", // this param is optional
options, // this param is optional
);
Meteor.settings
摘要
Meteor.settings
包含特定于部署的配置选项。您可以通过传递 --settings
选项(它采用包含 JSON 数据的文件的名称)到 meteor run
或 meteor deploy
来初始化设置。当直接运行服务器(例如从捆绑包中)时,您改为通过将 JSON 直接放入 METEOR_SETTINGS
环境变量中来指定设置。如果设置对象包含一个名为 public
的键,则 Meteor.settings.public
将在客户端和服务器上可用。Meteor.settings
的所有其他属性仅在服务器上定义。即使没有指定设置,您也可以依赖 Meteor.settings
和 Meteor.settings.public
在客户端和服务器上都被定义为对象(而不是未定义)。运行时对 Meteor.settings.public
的更改将被新的客户端连接获取。
Meteor.release
摘要
Meteor.release
是一个字符串,包含项目构建时使用的 版本 的名称(例如,"1.2.3"
)。如果项目使用 Meteor 的 git 检出进行构建,则它为 undefined
。
Meteor.isClient
摘要
布尔变量。如果在客户端环境中运行,则为真。
import { Meteor } from 'meteor/meteor';
/** @type {Boolean} */
if (Meteor.isClient) {
// do something
}
Meteor.isServer
摘要
布尔变量。如果在服务器环境中运行,则为真。
import { Meteor } from 'meteor/meteor';
/** @type {Boolean} */
if (Meteor.isServer) {
// do something
}
危险
Meteor.isServer
可用于限制代码运行的位置,但它不会阻止代码发送到客户端。任何您不想提供给客户端的敏感代码,例如包含密码或身份验证机制的代码,都应保存在 server
目录中。
Meteor.isCordova
摘要
布尔变量。如果在 Cordova 移动环境中运行,则为真。
import { Meteor } from 'meteor/meteor';
/** @type {Boolean} */
if (Meteor.isCordova) {
// do something
}
Meteor.isDevelopment
摘要
布尔变量。如果在开发环境中运行,则为真。
import { Meteor } from 'meteor/meteor';
/** @type {Boolean} */
if (Meteor.isDevelopment) {
// do something
}
Meteor.isProduction
摘要
布尔变量。如果在生产环境中运行,则为真。
import { Meteor } from 'meteor/meteor';
/** @type {Boolean} */
if (Meteor.isProduction) {
// do something
}
Meteor.isModern
摘要
布尔变量。如果在“现代”JS 环境中运行,则为真,由 modern
包确定。
import { Meteor } from 'meteor/meteor';
/** @type {Boolean} */
if (Meteor.isModern) {
// do something
}
Meteor.isTest
摘要
布尔变量。运行单元测试时为真(如果在完整应用程序模式下运行测试则为假)。
import { Meteor } from 'meteor/meteor';
/** @type {Boolean} */
if (Meteor.isTest) {
// do something
}
Meteor.isAppTest
摘要
布尔变量。如果针对您的应用程序运行测试,则为真,即 meteor test --full-app
。
import { Meteor } from 'meteor/meteor';
/** @type {Boolean} */
if (Meteor.isAppTest) {
// do something
}
Meteor.isPackageTest
摘要
布尔变量。如果针对 Meteor 包运行测试,则为真。
import { Meteor } from 'meteor/meteor';
/** @type {Boolean} */
if (Meteor.isPackageTest) {
// do something
}
方法 API
Meteor 方法是远程过程调用 (RPC),是由 Meteor.methods
定义并由 Meteor.call
调用的函数。
定义方法的最基本方法是提供一个函数
import { Meteor } from "meteor/meteor";
Meteor.methods({
sum(a, b) {
return a + b;
},
});
import { Meteor } from "meteor/meteor";
const result = await Meteor.callAsync("sum", 1, 2);
console.log(result); // 3
您可以使用 Meteor.methods
同时定义多个方法。
您可以将 Meteor.methods
视为定义服务器 API 的远程对象的一种方式。
一个更完整的示例
import { Meteor } from "meteor/meteor";
import { check } from "meteor/check";
import { LinksCollection } from "/imports/api/links";
Meteor.methods({
async addLink(link) {
check(link, String); // check if the link is a string
// Do stuff...
const linkID = await LinksCollection.insertAsync(link);
if (/* you want to throw an error */) {
throw new Meteor.Error('Something is wrong', "Some details");
}
return linkID;
},
bar() {
// Do other stuff...
return 'baz';
}
});
import React from "react";
import { Meteor } from "meteor/meteor";
function Component() {
const addLink = () =>
Meteor.callAsync(
"addLink",
"https://www.meteor.js.cn/tutorials/react/creating-an-app"
);
return (
<div>
<button onClick={addLink}>Add Link</button>
</div>
);
}
在服务器上调用 methods
定义了可以由客户端远程调用的函数。它们应该返回一个 EJSON 可处理的值或抛出一个异常。在您的方法调用内部,this
绑定到一个方法调用对象,该对象提供以下内容
isSimulation
:布尔值,如果此调用是存根,则为真。unblock
:调用时,允许来自此客户端的下一个方法开始运行。userId
:当前用户的 ID。setUserId
:将当前客户端与用户关联的函数。connection
:在服务器上,接收此方法调用的 连接。
在客户端上调用 methods
定义与相同名称的服务器方法关联的存根函数。如果您不想,则不必为您的方法定义存根。在这种情况下,方法调用就像其他系统中的远程过程调用一样,您必须等待服务器的结果。
如果您确实定义了存根,当客户端调用服务器方法时,它也会并行运行其存根。在客户端上,存根的返回值被忽略。存根是为了其副作用而运行的:它们旨在模拟服务器方法将执行的操作的结果,但无需等待往返延迟。如果存根抛出异常,它将记录到控制台。
您始终使用方法,因为数据库变异器(insert
、update
、remove
)是作为方法实现的。当您在客户端上调用这些函数中的任何一个时,您正在调用其更新本地缓存的存根版本,并将相同的写入请求发送到服务器。当服务器响应时,客户端使用服务器上实际发生的写入更新本地缓存。
您不必将所有方法定义都放入单个 Meteor.methods
调用中;您可以多次调用它,只要每个方法都有唯一的名称即可。
如果客户端调用一个方法并在收到响应之前断开连接,它将在重新连接时重新调用该方法。这意味着客户端可能多次调用一个方法,而实际上只需要调用一次。如果这种行为对您的方法造成问题,请考虑在客户端的每次方法调用中附加一个唯一的 ID,并在服务器上检查是否已经进行过具有此 ID 的调用。或者,您可以使用带有设置为 true 的 noRetry 选项的Meteor.apply
。
在 Meteor 指南的方法文章中了解更多关于方法及其使用方法的信息。
此方法可用于确定当前方法调用是否为异步调用。如果方法在服务器上运行并来自异步调用 (Meteor.callAsync
),则返回 true。
import { Meteor } from "meteor/meteor";
Meteor.methods({
async foo() {
return Meteor.isAsyncCall();
},
});
import { Meteor } from "meteor/meteor";
const result = await Meteor.callAsync("foo");
console.log(result); // true
Meteor.call("foo", (err, result) => {
console.log(result); // false
});
this.userId
用户 ID 是一个任意字符串,通常是数据库中用户记录的 ID。您可以使用 setUserId
函数设置它。如果您使用的是Meteor 账户系统,则此操作将为您处理。
import { Meteor } from "meteor/meteor";
Meteor.methods({
foo() {
console.log(this.userId);
},
});
this.setUserId
调用此函数以更改进行此方法调用的连接上当前登录的用户。这只是为在此连接上接收的未来方法调用设置 userId
的值。传递 null
以注销连接。
如果您使用的是内置的 Meteor 账户系统,则这应该对应于Meteor.users
集合中文档的 _id
字段。
setUserId
不是追溯性的。它会影响当前方法调用和此连接上的任何未来方法调用。此连接上的任何先前方法调用仍然会看到它们开始时有效的 userId
值。
如果您还想更改客户端上的登录用户,则在服务器上调用 setUserId
后,在客户端上调用 Meteor.connection.setUserId(userId)
。
import { Meteor } from "meteor/meteor";
Meteor.methods({
foo() {
this.setUserId("some-id");
},
});
this.connection
在方法调用内部访问。接收此方法的连接。如果方法与连接无关(例如,服务器发起的调用),则为 null。从服务器方法(该方法依次由客户端发起)发出的方法调用共享相同的连接。
Meteor.Error
摘要
此类表示方法抛出的符号错误。
参数
源代码名称 | 类型 | 描述 | 必需 |
---|---|---|---|
error | 字符串 | 唯一标识此类错误的字符串代码。调用方法的客户端应使用此字符串来确定要采取的适当操作,而不是尝试解析 reason 或 details 字段。 出于向后兼容性的原因,某些内置的 Meteor 函数(例如 | 是 |
reason | 字符串 | 可选。错误的简短人性化摘要,例如“未找到”。 | 否 |
details | 字符串 | 可选。有关错误的附加信息,例如文本堆栈跟踪。 | 否 |
import { Meteor } from "meteor/meteor"";
const error = new Meteor.Error(
"error",
"reason", // this param is optional
"details", // this param is optional
);
例如
import { Meteor } from "meteor/meteor";
// on the server, pick a code unique to this error
// the reason field should be a useful debug message
Meteor.methods({
methodName() {
throw new Meteor.Error(
"logged-out",
"The user must be logged in to post a comment."
);
},
});
import { Meteor } from "meteor/meteor";
// on the client
Meteor.call("methodName", function (error) {
// identify the error
if (error && error.error === "logged-out") {
// show a nice error message
Session.set("errorMessage", "Please log in to post a comment.");
}
});
如果您想从方法中返回错误,请抛出异常。方法可以抛出任何类型的异常。但是 Meteor.Error
是服务器将发送到客户端的唯一类型的错误。如果方法函数抛出其他异常,则它将在网络上映射到一个经过清理的版本。具体来说,如果抛出的错误上的 sanitizedError
字段设置为 Meteor.Error
,则该错误将发送到客户端。否则,如果没有可用的清理版本,客户端将收到 Meteor.Error(500, 'Internal server error')
。
Meteor.call
摘要
使用同步存根调用方法,并传递任意数量的参数。
参数
源代码名称 | 类型 | 描述 | 必需 |
---|---|---|---|
name | 字符串 | 要调用的方法名称 | 是 |
arg1, arg2... | EJSONable | 可选方法参数 | 否 |
asyncCallback | 函数 | 可选回调,在方法完成后异步调用,传递错误或结果。如果未提供,则方法将尽可能同步运行(见下文)。 | 否 |
这是使用同步存根调用方法的方法。它将在服务器上运行该方法。如果存在存根,它还将在客户端上运行存根。(另请参阅Meteor.apply
,它与 Meteor.call
相同,只是您将参数指定为数组而不是作为单独的参数,并且您可以指定一些控制方法执行方式的选项。)
如果您将回调函数作为最后一个参数包含在内(它不能是方法的参数,因为函数不可序列化),则该方法将异步运行:它不会返回任何特定内容,也不会抛出异常。当方法完成时(这可能在 Meteor.call
返回之前或之后发生),回调将被调用,并带有两个参数:error
和 result
。如果抛出错误,则 error
将是异常对象。否则,error
将为 undefined
,返回值(可能为 undefined
)将在 result
中。
// Asynchronous call
Meteor.call('foo', 1, 2, (error, result) => { ... });
如果您在服务器上不传递回调,则方法调用将阻塞,直到方法完成。它最终将返回方法的返回值,或者如果方法抛出异常,则会抛出异常。(如果异常发生在远程并且不是 Meteor.Error
异常,则可能会映射到 500 服务器错误。)
// Synchronous call
const result = Meteor.call("foo", 1, 2);
在客户端,如果您不传递回调并且不在存根内部,call
将返回 undefined
,并且您将无法获取方法的返回值。这是因为客户端没有 fiber,因此它实际上无法阻塞远程方法的执行。
最后,如果您在客户端的存根内部并调用另一个方法,则不会执行另一个方法(不会生成 RPC,不会发生任何“真实”的事情)。如果该其他方法具有存根,则该存根将替代该方法并执行。方法调用的返回值是存根函数的返回值。客户端在同步执行存根方面没有问题,这就是为什么客户端可以从方法体内部使用同步 Meteor.call
形式的原因,如前所述。
Meteor 跟踪客户端和服务器上方法执行的数据库写入,并且在服务器的所有写入替换本地缓存中的存根写入之前,不会调用 asyncCallback
。在某些情况下,方法返回值可用与写入可见之间可能存在延迟:例如,如果另一个未完成的方法写入同一文档,则本地缓存可能要等到其他方法也完成之后才会更新。如果您希望在方法的结果从服务器到达后立即处理它,即使方法的写入尚未可用,也可以将 onResultReceived
回调指定给Meteor.apply
。
警告
仅当调用不具有存根或具有同步存根的方法时,才使用 Meteor.call
。如果要调用具有异步存根的方法,可以使用 Meteor.callAsync
调用任何方法。
Meteor.callAsync
摘要
使用异步存根调用方法,并传递任意数量的参数。
参数
源代码名称 | 类型 | 描述 | 必需 |
---|---|---|---|
name | 字符串 | 要调用的方法名称 | 是 |
arg1, arg2... | EJSONable | 可选方法参数 | 否 |
import { Meteor } from "meteor/meteor";
/** @returns Promise */
const result = Meteor.callAsync(
"name",
{ num: 42 , someProp: "foo" }, // this param is optional
);
Meteor.callAsync
就像 Meteor.call
一样,只是它会返回一个 promise,您需要解决该 promise 才能获得结果。
Meteor.apply
摘要
调用方法并传递一个参数数组。
参数
源代码名称 | 类型 | 描述 | 必需 |
---|---|---|---|
name | 字符串 | 要调用的方法名称 | 是 |
args | Array.<EJSONable> | 方法参数 | 是 |
options | 对象 | 否 | |
asyncCallback | 函数 | 可选回调;语义与 | 否 |
import { Meteor } from "meteor/meteor";
Meteor.apply(
"name",
[{ num: 42 , someProp: "foo" }],
options, // this param is optional
() => {}, // this param is optional
);
Meteor.apply
就像 Meteor.call
一样,只是方法参数作为数组而不是直接作为参数传递,并且您可以指定有关客户端如何执行方法的选项。
警告
仅当调用不具有存根或具有同步存根的方法时,才使用 Meteor.apply
。如果要调用具有异步存根的方法,可以使用 Meteor.applyAsync
调用任何方法。
Meteor.applyAsync
摘要
调用方法并传递一个参数数组。
参数
源代码名称 | 类型 | 描述 | 必需 |
---|---|---|---|
name | 字符串 | 要调用的方法名称 | 是 |
args | Array.<EJSONable> | 方法参数 | 是 |
options | 对象 | 否 |
import { Meteor } from "meteor/meteor";
Meteor.applyAsync(
"name",
[{ num: 42 , someProp: "foo" }],
options, // this param is optional
);
Meteor.applyAsync
就像 Meteor.apply
一样,只是它是一个异步函数,并且它会认为存根是异步的。
发布和订阅
这些函数控制 Meteor 服务器如何发布记录集以及客户端如何订阅这些记录集。
Meteor.publish仅限服务器
仅限服务器
摘要
发布记录集。
Meteor.publish
:记录集的名称和每次客户端订阅该名称时 Meteor 将调用的_发布函数_。发布函数可以返回一个Collection.Cursor
,在这种情况下,Meteor 将将该游标的文档发布到每个订阅的客户端。您还可以返回一个 Collection.Cursor
数组,在这种情况下,Meteor 将发布所有游标。
警告
如果在一个数组中返回多个游标,它们当前必须都来自不同的集合。我们希望在未来的版本中取消此限制。
参数
源代码名称 | 类型 | 描述 | 必需 |
---|---|---|---|
name | 字符串或对象 | 如果是字符串,则为记录集的名称。如果是对象,则为发布函数的 publications 字典,按名称区分。如果是 | 是 |
func | 函数 | 每次客户端订阅时在服务器上调用的函数。在函数内部, | 是 |
import { Meteor } from "meteor/meteor";
import { check } from "meteor/check";
import { Rooms } from "/imports/api/Rooms";
import { Messages } from "/imports/api/Messages";
// Server: Publish the `Rooms` collection, minus secret info...
Meteor.publish("rooms", function () {
return Rooms.find(
{},
{
fields: { secretInfo: 0 },
}
);
});
// ...and publish secret info for rooms where the logged-in user is an admin. If
// the client subscribes to both publications, the records are merged together
// into the same documents in the `Rooms` collection. Note that currently object
// values are not recursively merged, so the fields that differ must be top
// level fields.
Meteor.publish("adminSecretInfo", function () {
return Rooms.find(
{ admin: this.userId },
{
fields: { secretInfo: 1 },
}
);
});
// Publish dependent documents and simulate joins.
Meteor.publish("roomAndMessages", function (roomId) {
check(roomId, String);
return [
Rooms.find(
{ _id: roomId },
{
fields: { secretInfo: 0 },
}
),
Messages.find({ roomId }),
];
});
或者,发布函数可以通过调用函数 added
(向发布的记录集中添加新文档)、changed
(更改或清除已发布记录集中文档的一些字段)和 removed
(从发布的记录集中删除文档)来直接控制其发布的记录集。这些方法由发布函数中的 this
提供。
如果发布函数不返回游标或游标数组,则假定它使用低级 added
/changed
/removed
接口,并且**还必须在初始记录集完成后调用一次 ready
**。
import { Mongo } from "meteor/mongo";
export const Rooms = new Mongo.Collection("rooms");
export const SecretData = new Mongo.Collection("messages");
import { Meteor } from "meteor/meteor";
import { check } from "meteor/check";
import { Rooms, SecretData } from "/imports/api/collections";
// Publish the current size of a collection.
Meteor.publish("countsByRoom", function (roomId) {
check(roomId, String);
let count = 0;
let initializing = true;
// `observeChanges` only returns after the initial `added` callbacks have run.
// Until then, we don't want to send a lot of `changed` messages—hence
// tracking the `initializing` state.
const handle = Messages.find({ roomId }).observeChanges({
added: (id) => {
count += 1;
if (!initializing) {
this.changed("counts", roomId, { count });
}
},
removed: (id) => {
count -= 1;
this.changed("counts", roomId, { count });
},
// We don't care about `changed` events.
});
// Instead, we'll send one `added` message right after `observeChanges` has
// returned, and mark the subscription as ready.
initializing = false;
this.added("counts", roomId, { count });
this.ready();
// Stop observing the cursor when the client unsubscribes. Stopping a
// subscription automatically takes care of sending the client any `removed`
// messages.
this.onStop(() => handle.stop());
});
// Sometimes publish a query, sometimes publish nothing.
Meteor.publish("secretData", function () {
if (this.userId === "superuser") {
return SecretData.find();
} else {
// Declare that no data is being published. If you leave this line out,
// Meteor will never consider the subscription ready because it thinks
// you're using the `added/changed/removed` interface where you have to
// explicitly call `this.ready`.
return [];
}
});
import { Meteor } from "meteor/meteor";
import { Mongo } from "meteor/mongo";
import { Session } from "meteor/session";
// Declare a collection to hold the count object.
const Counts = new Mongo.Collection("counts");
// Subscribe to the count for the current room.
Tracker.autorun(() => {
Meteor.subscribe("countsByRoom", Session.get("roomId"));
});
// Use the new collection.
const roomCount = Counts.findOne(Session.get("roomId")).count;
console.log(`Current room has ${roomCount} messages.`);
警告
如果在包含 autopublish
包的项目中调用 Meteor.publish
,Meteor 将发出警告消息。您的发布函数仍然可以工作。
在 Meteor 指南的 数据加载 文章中阅读有关发布和如何使用发布的更多信息。
这是常量。但是,如果已登录的用户发生更改,则发布函数将使用新值重新运行,假设它在之前的运行中没有抛出错误。
this.added仅限服务器
仅限服务器
摘要
在发布函数内部调用。通知订阅者已将文档添加到记录集中。
参数
源代码名称 | 类型 | 描述 | 必需 |
---|---|---|---|
集合 | 字符串 | 包含新文档的集合的名称。 | 是 |
ID | 字符串 | 新文档的 ID。 | 是 |
字段 | 对象 | 新文档中的字段。如果存在 | 是 |
// this is an instance of Subscription
this.added(
"collection",
"id",
fields,
);
this.changed仅限服务器
仅限服务器
摘要
在发布函数内部调用。通知订阅者记录集中的文档已修改。
参数
源代码名称 | 类型 | 描述 | 必需 |
---|---|---|---|
集合 | 字符串 | 包含已更改文档的集合的名称。 | 是 |
ID | 字符串 | 已更改文档的 ID。 | 是 |
字段 | 对象 | 文档中已更改的字段及其新值。如果 | 是 |
// this is an instance of Subscription
this.changed(
"collection",
"id",
fields,
);
this.removed仅限服务器
仅限服务器
摘要
在发布函数内部调用。通知订阅者已从记录集中删除文档。
参数
源代码名称 | 类型 | 描述 | 必需 |
---|---|---|---|
集合 | 字符串 | 已从中删除文档的集合的名称。 | 是 |
ID | 字符串 | 已删除的文档的 ID。 | 是 |
// this is an instance of Subscription
this.removed(
"collection",
"id",
);
this.ready仅限服务器
仅限服务器
摘要
在发布函数内部调用。通知订阅者已发送记录集的初始完整快照。这将触发对客户端上传递给 Meteor.subscribe
(如果有)的 onReady
回调的调用。
// this is an instance of Subscription
this.ready();
this.onStop仅限服务器
仅限服务器
摘要
在发布函数内部调用。注册一个回调函数,在订阅停止时运行。
参数
源代码名称 | 类型 | 描述 | 必需 |
---|---|---|---|
func | 函数 | 回调函数 | 是 |
// this is an instance of Subscription
this.onStop(
() => {}
);
如果在发布处理程序中调用 observe
或 observeChanges
,则此处是停止观察的位置。
this.error仅限服务器
仅限服务器
摘要
在发布函数内部调用。停止此客户端的订阅,触发对客户端上传递给 Meteor.subscribe
(如果有)的 onStop
回调的调用。如果 error
不是 Meteor.Error
,它将被 清理。
参数
源代码名称 | 类型 | 描述 | 必需 |
---|---|---|---|
error | 错误 | 要传递给客户端的错误。 | 是 |
// this is an instance of Subscription
this.error(
Error(error)
);
this.stop仅限服务器
仅限服务器
摘要
在发布函数内部调用。停止此客户端的订阅并调用客户端的 onStop
回调,不带任何错误。
// this is an instance of Subscription
this.stop();
Meteor.subscribe仅限客户端
仅限客户端
摘要
订阅记录集。返回一个句柄,该句柄提供 stop()
和 ready()
方法。
参数
源代码名称 | 类型 | 描述 | 必需 |
---|---|---|---|
name | 字符串 | 订阅的名称。与服务器的 | 是 |
arg1, arg2... | EJSONable | 传递给服务器上发布者函数的可选参数。 | 否 |
回调 | 函数或对象 | 可选。可能包括 | 否 |
订阅记录集时,它会告诉服务器将记录发送到客户端。客户端将这些记录存储在本地 Minimongo 集合 中,其名称与发布处理程序的 added
、changed
和 removed
回调中使用的 collection
参数相同。在客户端使用匹配的集合名称声明 Mongo.Collection
之前,Meteor 将对传入的记录进行排队。
// It's okay to subscribe (and possibly receive data) before declaring the
// client collection that will hold it. Assume 'allPlayers' publishes data from
// the server's 'players' collection.
Meteor.subscribe("allPlayers");
// The client queues incoming 'players' records until the collection is created:
const Players = new Mongo.Collection("players");
如果文档当前位于其任何订阅的已发布记录集中,则客户端将看到该文档。如果多个发布使用相同的 _id
发布同一集合的文档,则会为客户端合并这些文档。如果任何顶级字段的值发生冲突,则结果值将是已发布的值之一,任意选择。
警告
当前,当多个订阅发布同一文档时,仅比较顶级字段。这意味着如果文档包含同一顶级字段的不同子字段,则并非所有子字段都将在客户端上可用。我们希望在未来的版本中取消此限制。
当服务器 将订阅标记为已准备就绪 时,将不带任何参数调用 onReady
回调。如果订阅失败或被服务器终止,则将使用 Meteor.Error
调用 onStop
回调。如果通过调用订阅句柄上的 stop
或在发布内部停止订阅,则将不带任何参数调用 onStop
。
Meteor.subscribe
返回一个订阅句柄,它是一个具有以下属性的对象
import { Meteor } from "meteor/meteor";
const handle = Meteor.subscribe("allPlayers");
handle.ready(); // True when the server has marked the subscription as ready
handle.stop(); // Stop this subscription and unsubscribe from the server
handle.subscriptionId; // The id of the subscription this handle is for.
在 Tracker.autorun 内部运行 Meteor.subscribe 时,获得的句柄将始终具有相同的 subscriptionId 字段。如果将这些句柄存储在某些数据结构中,则可以使用它来对订阅句柄进行去重。
如果在反应式计算中调用 Meteor.subscribe
,例如使用 Tracker.autorun
,则当计算失效或停止时,订阅将自动取消;无需对从 autorun
内部进行的订阅调用 stop
。但是,如果运行函数的下一个迭代订阅了相同的记录集(相同的名称和参数),则 Meteor 足够智能,可以跳过浪费的取消订阅/重新订阅。例如
Tracker.autorun(() => {
Meteor.subscribe("chat", { room: Session.get("currentRoom") });
Meteor.subscribe("privateMessages");
});
这会让你订阅当前房间的聊天消息和你私人的消息。当你通过调用 Session.set('currentRoom', 'newRoom')
更改房间时,Meteor 将订阅新房间的聊天消息,取消订阅原始房间的聊天消息,并继续保持订阅你的私人消息。
发布策略
以下功能适用于 Meteor 2.4 或
[email protected]
一旦开始扩展应用程序,您可能希望更多地控制客户端如何处理发布中的数据。有三种发布策略
SERVER_MERGE
SERVER_MERGE
是默认策略。使用此策略时,服务器会维护连接订阅的所有数据的副本。这使我们能够仅通过多个发布发送增量。
NO_MERGE_NO_HISTORY
NO_MERGE_NO_HISTORY
策略会导致服务器将所有发布数据直接发送到客户端。它不记得以前发送给客户端的内容,并且在订阅停止时不会触发删除消息。这仅应在特殊用例(如发送并忘记队列)中选择。
NO_MERGE
NO_MERGE
与 NO_MERGE_NO_HISTORY
类似,但服务器会记住已发送给客户端的 ID,以便在订阅停止时可以删除它们。当集合仅在一个发布中使用时,可以使用此策略。
选择 NO_MERGE
后,客户端将优雅地处理重复事件,而不会抛出异常。具体来说
- 当我们收到已存在于客户端集合中的文档的添加消息时,它将被更改。
- 当我们收到客户端集合中不存在的文档的更改消息时,它将被添加。
- 当我们收到客户端集合中不存在的文档的删除消息时,不会发生任何事情。
您可以从 DDPServer
导入发布策略。
import { DDPServer } from "meteor/ddp-server";
const { SERVER_MERGE, NO_MERGE_NO_HISTORY, NO_MERGE } =
DDPServer.publicationStrategies;
您可以使用以下方法设置或获取发布的发布策略
setPublicationStrategy仅限服务器
仅限服务器
摘要
设置给定集合的发布策略。发布策略可从 DDPServer.publicationStrategies
获取。您可以从 Meteor.server
调用此方法,例如 Meteor.server.setPublicationStrategy()
参数
源代码名称 | 类型 | 描述 | 必需 |
---|---|---|---|
collectionName | 字符串 | ---- | 是 |
策略 | 对象 | ---- | 是 |
对于 foo
集合,您可以设置 NO_MERGE
策略,如所示
import { DDPServer } from "meteor/ddp-server";
Meteor.server.setPublicationStrategy(
"foo",
DDPServer.publicationStrategies.NO_MERGE
);
getPublicationStrategy仅限服务器
仅限服务器
摘要
获取请求的集合的发布策略。您可以从 Meteor.server
调用此方法,例如 Meteor.server.getPublicationStrategy()
参数
源代码名称 | 类型 | 描述 | 必需 |
---|---|---|---|
collectionName | 字符串 | ---- | 是 |
import { Meteor } from "meteor/meteor";
/** @returns Object */
const result = Meteor.server.getPublicationStrategy(
"collectionName"
);
服务器连接
用于管理和检查 Meteor 客户端与服务器之间网络连接的函数。
import { Meteor } from "meteor/meteor";
const status = Meteor.status();
console.log(status);
// ^^^^
// {
// connected: Boolean,
// status: String,
// retryCount: Number,
// retryTime: Number,
// reason: String,
// }
状态对象包含以下字段
connected
- 布尔值:如果当前已连接到服务器,则为真。如果为假,则更改和方法调用将排队,直到重新建立连接。status
- 字符串:描述当前的重新连接状态。可能的值包括connected
(连接已建立并运行)、connecting
(已断开连接并尝试打开新连接)、failed
(永久连接失败;例如,客户端和服务器支持不同的 DDP 版本)、waiting
(连接失败并等待尝试重新连接)和offline
(用户已断开连接)。retryCount
- 数字:连接丢失后,客户端尝试重新连接的次数。连接时为 0。retryTime
- 数字或未定义:下一次重新连接尝试的估计时间。要将其转换为下一次重新连接之前的间隔,此键仅在status
为waiting
时设置。您可以使用此代码段jsretryTime - new Date().getTime();
reason
- 字符串或未定义:如果status
为failed
,则说明连接失败的原因。
Meteor.reconnect仅限客户端
仅限客户端
摘要
如果客户端未连接到服务器,则强制立即尝试重新连接。
如果客户端已连接,则此方法不执行任何操作。
import { Meteor } from "meteor/meteor";
Meteor.reconnect();
Meteor.disconnect仅限客户端
仅限客户端
摘要
断开客户端与服务器的连接。
import { Meteor } from "meteor/meteor";
Meteor.disconnect();
调用此方法可断开与服务器的连接并停止所有实时数据更新。在客户端断开连接期间,它不会接收集合的更新,方法调用将排队,直到重新建立连接,并且热代码推送将被禁用。
调用 Meteor.reconnect 以重新建立连接并恢复数据传输。
这可用于在不需要实时更新时节省移动设备的电量。
import { Meteor } from "meteor/meteor";
const handle = Meteor.onConnection((connection) => {
console.log(connection);
// ^^^^^^^^^^^
// {
// id: String,
// close: Function,
// onClose: Function,
// clientAddress: String,
// httpHeaders: Object,
// }
});
handle.stop(); // Unregister the callback
onConnection
返回一个包含单个方法 stop
的对象。调用 stop
将取消注册回调函数,以便此回调函数不再在新的连接上被调用。
回调函数将接收一个参数,即表示客户端连接的服务器端 connection
对象。此对象包含以下字段
id
- 字符串:此连接的全局唯一 ID。close
- 函数:关闭此 DDP 连接。客户端可以自由重新连接,但如果重新连接,则会收到具有新id
的不同连接。onClose
- 函数:注册一个回调函数,在连接关闭时调用。如果连接已关闭,则会立即调用回调函数。clientAddress
- 字符串:客户端的 IP 地址,采用点分十进制格式(例如127.0.0.1
)。如果您在代理服务器后面运行 Meteor 服务器(以便客户端连接到代理服务器而不是直接连接到您的服务器),则需要设置HTTP_FORWARDED_COUNT
环境变量,以便clientAddress
报告正确的 IP 地址。将
HTTP_FORWARDED_COUNT
设置为一个整数,表示服务器前面的代理服务器数量。例如,当您的服务器位于一个代理服务器后面时,您将其设置为1
。httpHeaders
- 对象:当连接通过 HTTP 传输(例如使用 Meteor 的默认 SockJS 实现)时,此字段包含白名单 HTTP 标头。出于安全考虑,Cookie 会故意从标头中排除,因为它们对这种传输方式构成安全风险。有关详细信息和替代方案,请参阅 SockJS 文档。
当前,当客户端重新连接到服务器(例如在暂时失去 Internet 连接后),它每次都会获得一个新的连接。
onConnection
回调函数将再次被调用,并且新连接将具有新的连接id
。
将来,当客户端重新连接完全实现后,从客户端重新连接将重新连接到服务器上的同一连接:
onConnection
回调函数将不再为此连接调用,并且连接仍将具有相同的连接id
。
DDP.connect
摘要
连接到另一个 Meteor 应用程序的服务器,以订阅其文档集并调用其远程方法。
参数
源代码名称 | 类型 | 描述 | 必需 |
---|---|---|---|
url | 字符串 | 另一个 Meteor 应用程序的 URL。 | 是 |
options | 对象 | 否 |
import { DDP } from "meteor/ddp-client";
import { Mongo } from "meteor/mongo";
import { Meteor } from "meteor/meteor";
const options = {...};
const otherServer = DDP.connect("http://example.com", options);
otherServer.call("foo.from.other.server", 1, 2, function (err, result) {
// ...
});
Metepr.call("foo.from.this.server", 1, 2, function (err, result) {
// ...
});
const remoteColl = new Mongo.Collection("collectionName", { connection: otherServer });
remoteColl.find(...);
要调用另一个 Meteor 应用程序上的方法或订阅其数据集,请使用应用程序的 URL 调用 DDP.connect
。DDP.connect
返回一个对象,该对象提供
subscribe
- 订阅记录集。请参阅 Meteor.subscribe。call
- 调用方法。请参阅 Meteor.call。apply
- 使用参数数组调用方法。请参阅 Meteor.apply。methods
- 为远程服务器上定义的方法定义客户端专用存根。请参阅 Meteor.methods。status
- 获取当前连接状态。请参阅 Meteor.status。reconnect
- 请参阅 Meteor.reconnect。disconnect
- 请参阅 Meteor.disconnect。
默认情况下,客户端会打开与加载它们的服务器的连接。当您调用 Meteor.subscribe
、Meteor.status
、Meteor.call
和 Meteor.apply
时,您正在使用连接返回到该默认服务器。
DDP.onReconnect
摘要
注册一个函数,作为重新连接的第一步调用。此函数可以调用将在任何其他未完成方法之前执行的方法。例如,这可用于在连接上重新建立适当的身份验证上下文。
import { DDP } from "meteor/ddp-client";
DDP.onReconnect(
() => {}
);
计时器
Meteor 使用全局环境变量来跟踪诸如当前请求的用户之类的事情。为了确保这些变量具有正确的价值,您需要使用 Meteor.setTimeout
而不是 setTimeout
以及 Meteor.setInterval
而不是 setInterval
。
这些函数的工作原理与其本机 JavaScript 等效项完全相同。如果您调用本机函数,您将收到一条错误消息,指出 Meteor 代码必须始终在 Fiber 中运行,并建议使用 Meteor.bindEnvironment
。
Meteor.setTimeout
摘要
在等待指定延迟后,将来调用一个函数。
参数
源代码名称 | 类型 | 描述 | 必需 |
---|---|---|---|
func | 函数 | 要运行的函数 | 是 |
延迟 | 数字 | 在调用函数之前要等待的毫秒数 | 是 |
import { Meteor } from "meteor/meteor";
Meteor.setTimeout(
() => {},
42,
);
返回一个句柄,可由 Meteor.clearTimeout
使用。
Meteor.setInterval
摘要
重复调用一个函数,并在每次调用之间设置时间延迟。
参数
源代码名称 | 类型 | 描述 | 必需 |
---|---|---|---|
func | 函数 | 要运行的函数 | 是 |
延迟 | 数字 | 每次函数调用之间要等待的毫秒数。 | 是 |
import { Meteor } from "meteor/meteor";
Meteor.setInterval(
() => {},
42,
);
返回一个句柄,可由 Meteor.clearInterval
使用。
Meteor.clearTimeout
摘要
取消由 Meteor.setTimeout
调度的函数调用。
参数
源代码名称 | 类型 | 描述 | 必需 |
---|---|---|---|
ID | 对象 |
| 是 |
import { Meteor } from "meteor/meteor";
Meteor.clearTimeout(
id
);
Meteor.clearInterval
摘要
取消由 Meteor.setInterval
调度的重复函数调用。
参数
源代码名称 | 类型 | 描述 | 必需 |
---|---|---|---|
ID | 对象 |
| 是 |
import { Meteor } from "meteor/meteor";
Meteor.clearInterval(
id
);
环境变量
Meteor 使用 AsyncLocalStorage 实现 Meteor.EnvironmentVariable
,它允许跨异步边界维护上下文。Meteor.EnvironmentVariable
与 Meteor.bindEnvironment
、Promise 和许多其他 Meteor API 协同工作,以在异步代码中保留上下文。它在 Meteor 中的一些使用示例是在方法中存储当前用户,以及在使用 audit-argument-checks
时记录已检查的参数。
import { Meteor } from "meteor/meteor";
const currentRequest = new Meteor.EnvironmentVariable();
function log(message) {
const requestId = currentRequest.get() || "None";
console.log(`[${requestId}]`, message);
}
currentRequest.withValue("12345", () => {
log("Handling request"); // Logs: [12345] Handling request
});
Meteor.EnvironmentVariable
摘要
EnvironmentVariable 的构造函数
import { Meteor } from "meteor/meteor"";
const environmentVariable = new Meteor.EnvironmentVariable();
);
Meteor.EnvironmentVariableAsync
摘要
EnvironmentVariable 的构造函数
import { Meteor } from "meteor/meteor"";
const environmentVariableAsync = new Meteor.EnvironmentVariableAsync();
);
Meteor.EnvironmentVariable.get
摘要
变量当前值的获取器,如果从 withValue
回调函数外部调用,则为 undefined
。
import { Meteor } from "meteor/meteor";
/** @returns any */
const result = Meteor.EnvironmentVariable.get();
Meteor.EnvironmentVariable.withValue
摘要
接收一个值和一个函数,在调用期间设置该值并调用该函数
import { Meteor } from "meteor/meteor";
/** @returns Promise<any> */
const result = Meteor.EnvironmentVariable.withValue(
any,
() => {},
options, // this param is optional
);
Meteor.bindEnvironment
摘要
存储当前的 Meteor 环境变量,并包装要使用恢复的环境变量运行的函数。在服务器上,该函数在 Async Local Storage 中包装。
此函数有两个原因
- 返回要在 MeteorJS 上下文中执行的函数,将其分配在 Async Local Storage 中。
- 更好的错误处理,错误消息将更加清晰。
参数
源代码名称 | 类型 | 描述 | 必需 |
---|---|---|---|
func | 函数 | 要包装的函数 | 是 |
onException | 函数 | ---- | 是 |
_this | 对象 | 可选的 | 是 |
import { Meteor } from "meteor/meteor";
/** @returns function */
const result = Meteor.bindEnvironment(
() => {},
() => {},
_this,
);