关于 meteor-methods
用于实现 Meteor methods 的技能,即客户端调用的服务器端数据变更接口。内容涵盖参数验证、乐观 UI 存根、速率限制和错误处理,面向 Meteor 开发者。
主要功能
- 01异步服务器端方法
- 02使用 check() 验证参数
- 03乐观 UI 客户端存根
- 04DDP 方法速率限制
- 05客户端可见的错误处理
适用场景
- 01构建经过验证的服务器端变更
- 02显示乐观的本地更新
- 03限制敏感方法的调用频率
- 04处理方法和传输错误
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ meteor/ agent-skills --skill meteor-methods安装后在 Claude Code 中输入/meteor-methods确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/check-and-validate.mdeval-cases.mdrate-limiting.md详细介绍
Meteor 方法
方法是 Meteor 用于从客户端发起服务端数据修改的基本机制。 在 Meteor 3 中,服务端方法是异步的。延迟补偿仍通过客户端存根实现。
决策流程
- 这段代码是否会修改服务端数据?使用方法。
- 客户端是否需要在服务端响应之前读取结果?编写一个同名的客户端存根;它会修改本地 Minimongo 集合,如果服务端结果不一致,这些更改就会回滚。
- 方法是否接受不可信的输入?使用
check()验证每个参数。否则,Agent 应拒绝编写该方法。 - 方法是否对速率敏感?添加
DDPRateLimiter.addRule。
脚手架
import { Meteor } from "meteor/meteor";
import { check, Match } from "meteor/check";
Meteor.methods({
async addItem(payload) {
check(payload, {
title: String,
qty: Match.Integer,
});
if (!this.userId) {
throw new Meteor.Error("not-authorized");
}
const _id = await Items.insertAsync({
...payload,
ownerId: this.userId,
createdAt: new Date(),
});
return _id;
},
});
从客户端调用
try {
const id = await Meteor.callAsync("addItem", { title: "Hi", qty: 1 });
setLocalId(id);
} catch (err) {
if (err && typeof err === "object" && "error" in err) {
console.error(err.error, err.reason, err.details);
} else {
console.error("local or transport failure", err);
}
}
乐观 UI
在客户端定义同一个方法。客户端存根会立即对本地 Minimongo 执行操作;服务端的权威结果会回滚任何不一致之处。
// client/methods.js
import { Meteor } from "meteor/meteor";
import { Random } from "meteor/random";
Meteor.methods({
addItem(payload) {
Items.insert({
...payload,
_id: Random.id(),
ownerId: Meteor.userId(),
createdAt: new Date(),
});
},
});
如果只需要同步的 Minimongo 操作,同步存根最简单。callAsync 也支持异步存根;当同一个方法定义在客户端和服务端运行,并使用 *Async 集合调用时,异步存根很有用。
异步存根可以等待基于微任务的本地操作,但不能等待 fetch、计时器、IndexedDB、工作线程或其他浏览器宏任务 API。应在存根之外执行外部 I/O。
速率限制
import { DDPRateLimiter } from "meteor/ddp-rate-limiter";
DDPRateLimiter.addRule(
{
type: "method",
name: "addItem",
userId: (userId) => Boolean(userId),
},
5, // operations
10000, // per 10s
);
Meteor 3.5+ 允许为数据库决策使用异步匹配器。在 Meteor 3.0 到 3.4 中,匹配器必须保持同步;应使用固定规则、预先计算的同步状态,或升级版本,而不是在匹配器中等待 Mongo。
Meteor 会在传入连接的消息队列中依次等待异步匹配器。只投影所需字段,并确保查询足够快。如果匹配器 Promise 被拒绝,该次调用就会报错;请明确测试这种情况。
有关规则对象的架构,以及按连接与按用户设置键的说明,请参阅 references/rate-limiting.md。
错误处理
对于有意让客户端可见的失败,抛出 Meteor.Error(code, reason, details?)。普通 Error 会在服务端记录日志,并在发送给客户端前进行脱敏,变为 Meteor.Error(500, "Internal server error");其原始消息和堆栈不会暴露。Meteor.Error 包含其代码、原因和详情。不要假设每个 callAsync 拒绝都会是这种格式:回调误用、传输失败和本地存根异常都可能产生原生错误或其他错误。读取 Meteor 专属字段之前,先缩小捕获值的类型范围。
反模式
- 未对每个参数使用
check()的方法。应在代码审查中拒绝此类方法。 - 将同一个方法用于已认证和未认证的调用。应拆分为两个方法。
- 在客户端存根中等待
fetch或计时器等浏览器宏任务 API。异步存根是有效的,但这些 API 会让无关代码在乐观模拟完成前运行。 - 在异步方法体内调用
Meteor.user()。请使用this.userId。
另请参阅
references/check-and-validate.mdreferences/rate-limiting.mdreferences/eval-cases.md