跳转到内容
搜索文档

API 参考

最后更新 查看 MarkdownAgent 设置

本页面介绍了 Worker Loader 绑定 API,假设您已将此类绑定配置env.LOADER

load

env.LOADER.load(code WorkerCode) WorkerStub

从提供的 WorkerCode 加载 Worker 并返回一个可以用来调用该 Worker 的 WorkerStub

get() 不同,load() 不会按 ID 缓存。每次调用都会创建一个新的 Worker。

当代码始终是新的时(例如,一次性 AI 生成的工具调用),请使用 load()

get

env.LOADER.get(id string, getCodeCallback () => Promise<WorkerCode>): WorkerStub

加载具有给定 ID 的 Worker,返回一个可以用来调用该 Worker 的 WorkerStub

为方便起见,加载器实现了 isolate 的缓存。当第一次看到一个新的 ID 时,会加载一个新的 isolate。但是,isolate 可能会在内存中保持预热一段时间。如果加载器的后续调用请求相同的 ID,可能会再次返回现有的 isolate,而不是创建一个新的。但不能保证一定如此:相同 ID 的后续调用也可能会从头启动一个新的 isolate。

只要系统决定需要启动一个新的 isolate,且尚未缓存该代码的副本,它就会调用 codeCallback 来获取 Worker 的代码。这是一个异步的回调,因此应用程序可以根据需要从远程存储加载代码。回调将返回一个 WorkerCode 对象(如下所述)。

由于缓存机制的存在,您应确保针对相同 ID 调用的回调始终返回完全相同的内容。如果内容的任何部分发生了改变,您必须使用一个新的 ID。但如果内容没有改变,最好重用相同的 ID,以便利用缓存。如果 WorkerCode 每次都不同,您可以传递一个随机 ID。

例如,您可以使用格式为 <worker-name>:<version-number> 的 ID,每次代码更改时,版本号都会递增。或者,您可以根据代码和配置的哈希值计算 ID,以便任何更改都会产生新的 ID。

get() 返回一个 WorkerStub,可用于向加载的 Worker 发送请求。请注意,stub 是同步返回的——您不需要等待(await)它。如果 Worker 尚未加载完成,对 stub 发出的请求将等待 Worker 加载,然后再传递。如果加载失败,请求将抛出异常。

这不保证两个请求会发送到相同的 isolate。即使您使用同一个 WorkerStub 发出多个请求,它们也可以在不同的 isolate 中执行。传递给 loader.get() 的回调可能被调用任意次(尽管多次调用是比较少见的情况)。

WorkerCode

这是 getCodeCallback 返回代表一个 worker 的结构。

compatibilityDate string

Worker 的兼容性日期。这与 Wrangler 配置文件中的 compatibility_date 设置具有相同的含义。

compatibilityFlags string[]可选

可选的兼容性标志列表,用于增强兼容性日期。这与 Wrangler 配置文件中的 compatibility_flags 设置具有相同的含义。

allowExperimental boolean可选

如果为 true,则在 compatibilityFlags 中将允许使用实验性的兼容性标志。要设置这个值,调用加载器的 worker 自身必须设置了 "experimental" 兼容性标志。实验性标志不能在生产环境中启用。

mainModule string

Worker 的主模块名称。它必须是 modules 中列出的模块之一。

modules Record<string, string | Module>

将模块名称映射到其字符串内容的字典对象。如果模块内容是纯字符串,则模块名称必须具有指示其类型的扩展名:.js.py

模块的内容也可以指定为一个对象,以便独立于名称指定其类型。允许的对象包括:

  • {js: string}: 使用 ES 模块语法进行导入和导出的 JavaScript 模块。
  • {cjs: string}: 使用 require() 语法进行导入的 CommonJS 模块。
  • {py: string}: 一个 Python 模块。请参阅下面的警告。
  • {text: string}: 一个可导入的字符串值。
  • {data: ArrayBuffer}: 一个可导入的 ArrayBuffer 值。
  • {json: object}: 一个可导入的对象。该值必须是 JSON 可序列化的。然而,请注意,值作为已解析的对象提供,并作为已解析的对象传递;两边都不会真正看到 JSON 序列化的过程。

globalOutbound ServiceStub | null可选

控制动态 Worker 是否能够访问网络。可以阻止或重定向全局的 fetch()connect() 函数(分别用于发出 HTTP 请求和建立 TCP 连接),从而隔离 Worker。

如果不指定 globalOutbound,默认会继承父级的网络访问权限,这通常意味着动态 Worker 将具有对公共互联网的完全访问权限。

如果 globalOutboundnull,则动态 Worker 将完全切断网络连接。fetch()connect() 都会抛出异常。

globalOutbound 也可以设置为任何服务绑定,包括父 worker env 中的服务绑定,以及来自 ctx.exports 的环回绑定 (loopback bindings)

使用 ctx.exports 特别有用,因为它允许您通过设置应传回给它的 ctx.props 值,针对特定的沙箱进一步自定义绑定。props 可以包含用于标识发出请求的特定动态 Worker 的信息。

例如:

import { WorkerEntrypoint } from "cloudflare:workers";

export class Greeter extends WorkerEntrypoint {
	fetch(request) {
		return new Response(`Hello, ${this.ctx.props.name}!`);
	}
}

export default {
	async fetch(request, env, ctx) {
		let worker = env.LOADER.get("alice", () => {
			return {
				// 将 worker 的全局出站重定向,把所有请求发送到 `Greeter` 类,
				// 在 `ctx.props.name` 中填入名字 "Alice",
				// 以便它总是响应 "Hello, Alice!"。
				globalOutbound: ctx.exports.Greeter({ props: { name: "Alice" } }),

				// ... 代码 ...
			};
		});

		return worker.getEntrypoint().fetch(request);
	},
};

env object

提供给动态 Worker 的环境对象。

使用此对象,您可以为 Worker 提供自定义的绑定。

env 被序列化并传递到动态 Worker 中,在那里它被直接用作 env 的值。它可以包含:

第二点是创建自定义绑定的关键:您可以通过定义一个实现 RPC API 的 WorkerEntrypoint,然后将其作为 Service Binding 提供给动态 Worker,来定义一个具有任何任意 API 的绑定。

此外,通过使用 ctx.exports 环回绑定,您可以通过设置 ctx.props 进一步为特定的动态 Worker 自定义绑定,就像上面对 globalOutbound 描述的一样。

import { WorkerEntrypoint } from "cloudflare:workers";

// 实现一个可以被动态 Worker 调用的绑定。
export class Greeter extends WorkerEntrypoint {
	greet() {
		return `Hello, ${this.ctx.props.name}!`;
	}
}

export default {
	async fetch(request, env, ctx) {
		let worker = env.LOADER.get("alice", () => {
			return {
				env: {
					// 提供一个具有 greet() 方法的绑定,可以被调用以接收问候语。
					// 绑定知道 Worker 的名字。
					GREETER: ctx.exports.Greeter({ props: { name: "Alice" } }),
				},

				// ... 代码 ...
			};
		});

		return worker.getEntrypoint().fetch(request);
	},
};

tails ServiceStub[]可选

您可以指定一个或多个 Tail Workers,它们将观察控制台日志、错误以及有关动态加载 worker 执行的其他细节。当向动态加载的 Worker 发出的请求完成时,tail 事件将被传递给 Tail Worker。和以往一样,您可以将 Tail Worker 实现为父 Worker 中的替代入口点,并使用 ctx.exports 引用它:

import { WorkerEntrypoint } from "cloudflare:workers";

export default {
	async fetch(request, env, ctx) {
		let worker = env.LOADER.get("alice", () => {
			return {
				// 将日志、错误等发送到 `LogTailer`。我们在 `ctx.props` 中传递 `name`,
				// 以便 `LogTailer` 知道是什么生成了这些日志。
				// (您可以在 `props` 中传递任何想要的内容。)
				tails: [ctx.exports.LogTailer({ props: { name: "alice" } })],

				// ... 代码 ...
			};
		});

		return worker.getEntrypoint().fetch(request);
	},
};

export class LogTailer extends WorkerEntrypoint {
	async tail(events) {
		let name = this.ctx.props.name;

		// 将日志发送到我们的日志端点,在 URL 中指定 worker 的名字。
		//
		// 请注意,在这种情况下,`events` 将始终是一个大小为 1 的数组,
		// 描述了传递给动态加载的 Worker 的事件。
		await fetch(`https://example.com/submit-logs/${name}`, {
			method: "POST",
			body: JSON.stringify(events),
		});
	}
}

这篇文档对您有帮助吗?