简介
网站可以记住深色主题或首选语言等显示选项。这些设置通常每次访问都会读取,但只有偶尔才会更改,因此很适合用作 Workers KV 的示例。你不会只存储一个表示功能开关的单词,而是要存储 JSON:一种将多个命名字段组合成一个值的文本格式。Worker 会将这段文本转换回可使用的设置。
在本实验中,Alice 和 Bob 只是虚构的账户标签,不是真实用户。你将为他们设置不同的偏好,并让缺失或损坏的条目返回合理的默认值。你还会附加 元数据,也就是与值一起存储的简短描述,用于标识设置的版本。版本号有助于说明读取的是哪份数据,但不能保证每个位置都会立即看到最新值。
请先完成「创建功能开关存储」实验。本实验从全新的 VM 开始,项目目录为 /home/labex/project/account-preferences,其中已经安装了 Node.js 22.22.0 和项目本地的 Wrangler 4.131.1。你将在学习账户中创建一个新的 Worker 和命名空间,并使用相同的账户读取、Worker 写入和 KV 写入权限。公开演示只会提供虚构的显示设置;URL 中的账户标签不具备身份验证功能。这个小练习不需要付费升级或购买域名。离开 VM 前,请完成资源清理。
连接偏好设置命名空间
在本步骤中,你将为示例账户偏好设置连接一个独立的命名空间。命名空间用于归类此服务的值;PREFERENCES 绑定为 Worker 提供一个稳定的访问名称。这个全新的 VM 会复用你的账户知识,但不会复用上一个实验中的命名空间或授权。
进入准备好的项目目录:
cd /home/labex/project/account-preferences
生成一次唯一名称。openssl rand -hex 6 会输出随机后缀;$(...) 会将该后缀插入名称。Shell 变量会让后续命令能够继续使用这个终端中的名称。
WORKER_NAME="labex-prefs-$(openssl rand -hex 6)"
printf '%s\n' "$WORKER_NAME"
为此 VM 授权。除了读取账户身份之外,Workers Scripts Write 允许部署和删除 Worker,Workers KV Write 允许管理本实验的命名空间和键。
npx wrangler login --device --browser=false --scopes account:read user:read workers_scripts:write workers_kv:write
在浏览器中打开显示的设备链接,输入当前验证码,检查请求的权限和学习账户,然后授权 Wrangler。授权页面中也可能出现后台访问权限。返回终端并等待登录完成。
展开 Developer Platform,检查 Workers Scripts Write 和 Workers KV Storage Write。这些权限与「创建功能开关存储」实验中介绍的资源管理权限相同。
npx wrangler whoami --json
确认输出中包含 loggedIn: true 以及学习账户的 name,即使列表中只有一个账户也要确认。复制该账户的 id。在运行下面的命令前,将配置中的 YOUR_ACCOUNT_ID 替换为这个 ID。这里的 cat here-document 会将两个 JSON 行之间的全部内容写入文件;> 会替换文件内容。未加引号的分隔符允许 Shell 插入 $WORKER_NAME。
cat > wrangler.jsonc <<JSON
{
"name": "$WORKER_NAME",
"main": "src/index.js",
"compatibility_date": "2026-07-30",
"account_id": "YOUR_ACCOUNT_ID",
"workers_dev": true
}
JSON
在该账户中创建命名空间。命名空间标题会使用 Worker 的唯一名称,方便你之后识别这两个资源。--update-config=false 会保留手动编辑绑定的步骤,不会自动修改文件。
npx wrangler kv namespace create "$WORKER_NAME-preferences" --update-config=false
输出中会包含新命名空间的 ID。复制该 ID,然后在下面的完整配置中替换 YOUR_ACCOUNT_ID 和 YOUR_NAMESPACE_ID。PREFERENCES 绑定名称由代码使用;ID 则用于标识真实的 Cloudflare 资源。
cat > wrangler.jsonc <<JSON
{
"name": "$WORKER_NAME",
"main": "src/index.js",
"compatibility_date": "2026-07-30",
"account_id": "YOUR_ACCOUNT_ID",
"workers_dev": true,
"kv_namespaces": [
{ "binding": "PREFERENCES", "id": "YOUR_NAMESPACE_ID" }
]
}
JSON
npx wrangler kv namespace list
找到本实验的命名空间标题,并将其 ID 与配置文件中的 ID 进行比较。列表中可能还有其他命名空间;不要修改它们。此配置记录了后续命令应使用的账户和资源。绑定是对命名空间的引用,不是命名空间数据的副本。
存储 JSON 值和版本元数据
在本步骤中,你将准备一个包含普通设置和两个真实数据错误的小型数据集。JSON 使用双引号包围字段名和字符串。命令参数外层的单引号可以防止 Shell 解释 JSON 中的双引号。
写入本地条目。Alice 偏好深色模式和英语;Bob 偏好浅色模式和法语。--metadata 会为键附加一个独立的 JSON 对象。这里的 revision 数字只是已保存版本的标签,不是安全决策,也不是自动递增的更新计数器。
npx wrangler kv key put account:alice '{"theme":"dark","language":"en"}' --binding PREFERENCES --local --metadata '{"revision":7}'
npx wrangler kv key put account:bob '{"theme":"light","language":"fr"}' --binding PREFERENCES --local --metadata '{"revision":8}'
npx wrangler kv key put account:broken 'not-json' --binding PREFERENCES --local
npx wrangler kv key put account:invalid '{"theme":"neon","language":"en"}' --binding PREFERENCES --local
account:broken 中的文本无法解析为 JSON。account:invalid 是有效的 JSON,但指定了应用不支持的主题。保留这两种情况,可以帮助你区分 解析——读取文本结构——与 验证——检查字段是否符合应用要求。不要为 Charlie 创建条目;后面会用它测试缺失键的处理路径。
npx wrangler kv key list --binding PREFERENCES --local
找到四个键名。Alice 和 Bob 应分别带有版本元数据 7 和 8。另外两个条目没有元数据。列表会显示名称和元数据,但不会显示每个值的完整内容。
npx wrangler kv key get account:alice --binding PREFERENCES --local --text
预期输出为 {"theme":"dark","language":"en"}。该命令只读取值,因此版本号不会出现在这段 JSON 文本中。
现在,将相同的四个虚构测试条目写入本实验的云端命名空间。这些明确指定的远程命令是独立操作:本地写入不会自动上传到 Cloudflare。
npx wrangler kv key put account:alice '{"theme":"dark","language":"en"}' --binding PREFERENCES --remote --metadata '{"revision":7}'
npx wrangler kv key put account:bob '{"theme":"light","language":"fr"}' --binding PREFERENCES --remote --metadata '{"revision":8}'
npx wrangler kv key put account:broken 'not-json' --binding PREFERENCES --remote
npx wrangler kv key put account:invalid '{"theme":"neon","language":"en"}' --binding PREFERENCES --remote
npx wrangler kv key list --binding PREFERENCES --remote
确认列表中包含相同的四个键名及其版本元数据。这些记录仅用于演示,之后可以丢弃。不要修改无关的命名空间。
使用安全默认值读取偏好设置
在本步骤中,你将编写一个处理程序,同时读取值和元数据。getWithMetadata() 会返回一个包含 value 和 metadata 字段的对象。键不存在时,value 为 null。即使值存在,metadata 也可能是 null。
写入此处理程序。带引号的 JS here-document 会原样保留代码。路由接受一个简短的小写账户标签,并构建类似 account:alice 的独立键;它不会将上一个请求的账户保存到全局变量中。
cat > src/index.js <<'JS'
function fallback(account, source) {
return Response.json({
account, theme: "light", language: "en", source, revision: null
});
}
export default {
async fetch(request, env) {
const match = new URL(request.url).pathname.match(/^\/preferences\/([a-z]{1,20})$/);
if (!match) return new Response("Not found", { status: 404 });
const account = match[1];
let entry;
try {
entry = await env.PREFERENCES.getWithMetadata(`account:${account}`, "text");
} catch {
return Response.json({ error: "Preferences temporarily unavailable" }, { status: 503 });
}
if (entry.value === null) return fallback(account, "missing");
let preferences;
try {
preferences = JSON.parse(entry.value);
} catch {
return fallback(account, "invalid");
}
if (!preferences || typeof preferences !== "object" || Array.isArray(preferences) ||
!["light", "dark"].includes(preferences.theme) ||
!["en", "fr"].includes(preferences.language)) {
return fallback(account, "invalid");
}
const revision = Number.isInteger(entry.metadata?.revision) && entry.metadata.revision > 0
? entry.metadata.revision : null;
return Response.json({
account, theme: preferences.theme, language: preferences.language,
source: "stored", revision
});
}
};
JS
第一个 try/catch 会处理 KV 读取不可用的情况,并返回 HTTP 503,表示服务暂时不可用。它不会错误地把账户当作不存在。先以 "text" 读取,再在单独的 try/catch 中解析,可以识别损坏的 JSON,而不会将其与存储故障混淆。使用 "json" 选项可以自动解析,但本实验将这两个操作分开,以便清楚地看到各自的错误处理路径。
缺失或无效的偏好设置都会回退到浅色模式和英语。source 字段会说明为什么使用回退值。对于有效值,响应只使用受支持的主题和语言字段。entry.metadata?.revision 可以安全处理缺失的元数据;只有正整数版本号才会显示,否则为 null。这些默认值适合保证可选的显示设置仍然可用,但不能替代身份验证或权限控制。
启动本地 Worker,保存其进程 ID,然后等待就绪消息:
npx wrangler dev --local --ip 0.0.0.0 --port 8080 > local.log 2>&1 &
DEV_PID=$!
cat local.log
后台进程会让终端保持可用;local.log 保存启动输出。如果启动尚未完成,请重复执行读取日志的命令。请求以下每种情况:
curl -i http://127.0.0.1:8080/preferences/alice
curl -i http://127.0.0.1:8080/preferences/bob
curl -i http://127.0.0.1:8080/preferences/charlie
curl -i http://127.0.0.1:8080/preferences/broken
curl -i http://127.0.0.1:8080/preferences/invalid
五种请求都应返回 HTTP 200 和 JSON。检查它们之间的差异:
| 账户 | 主题 | 语言 | 来源 | 版本 |
|---|---|---|---|---|
| alice | dark | en | stored | 7 |
| bob | light | fr | stored | 8 |
| charlie | light | en | missing | null |
| broken | light | en | invalid | null |
| invalid | light | en | invalid | null |
例如,Alice 的响应正文为 {"account":"alice","theme":"dark","language":"en","source":"stored","revision":7}。在 Bob 之后再次请求 Alice,设置仍应属于 Alice。完成清理前,请保持本地服务器运行。
验证已部署的偏好设置服务
在本步骤中,你将针对云端命名空间运行相同的测试。独立的云端检查可以验证所选账户、已部署的命名空间绑定、已存储的记录以及实际的 HTTP 响应。
npx wrangler deploy
确认输出中的 Worker 名称和 PREFERENCES 绑定。将部署后的公开地址复制到下面的变量中,并替换示例值:
WORKER_URL="https://YOUR_WORKER.YOUR_SUBDOMAIN.workers.dev"
curl -i "$WORKER_URL/preferences/alice"
curl -i "$WORKER_URL/preferences/bob"
curl -i "$WORKER_URL/preferences/charlie"
curl -i "$WORKER_URL/preferences/broken"
curl -i "$WORKER_URL/preferences/invalid"
将五个响应与本地表格进行比较。Alice 和 Bob 必须保留各自的偏好设置和版本元数据;Charlie 以及两个损坏的记录必须使用前面说明的默认值。如果刚写入的条目暂时不可见,请等待 KV 完成传播后重试。公开主机名在首次部署后也可能需要等待一段时间。连接错误不能算作回退响应。
在 Dashboard 中选择学习账户,打开 Storage & databases → Workers KV,找到本实验的 labex-prefs-...-preferences 命名空间。选择 KV Pairs,检查四条记录,点击 account:alice 旁的 View,将 JSON 值与终端输出比较。此视图显示键和值;修订元数据应通过前面的 Wrangler 键列表和 API 响应进行核对。你的唯一命名空间名称和 ID 会与示例不同。

公开端点只用于演示虚构的显示设置。真实的私有偏好设置服务会先识别请求者,再决定请求者可以访问哪个账户键。
删除临时云资源
在本步骤中,Wrangler 仍处于授权状态,你将删除这两个资源。命名空间的生命周期可能超过 Worker,因此仅删除应用不会清理其中的数据。
停止在此终端中启动的本地开发进程:
kill "$DEV_PID"
删除任何资源前,先检查已保存的资源引用:
cat wrangler.jsonc
确认其中的 labex-prefs-... Worker 名称和 PREFERENCES 命名空间 ID。删除此配置所选中的 Worker:
npx wrangler delete
如果出现提示,请确认显示的名称与本实验匹配,然后输入 y 确认。接着,只删除 PREFERENCES 引用的命名空间:
npx wrangler kv namespace delete --binding PREFERENCES
接受任何确认提示前,先检查其中显示的命名空间。保留 wrangler.jsonc 不变,以便独立检查能够识别本应不存在的资源。
npx wrangler kv namespace list
本实验的命名空间应已不在列表中;无关的命名空间应保留。刷新 Dashboard 中的列表,确认本实验的 Worker 和命名空间已经消失。请求失败或登录过期都不能证明删除成功。请在退出登录前运行本步骤的检查,以便它可以读取已授权的资源清单。
结束 VM 授权
在本步骤中,确认清理检查通过后,断开 Wrangler 的授权。退出登录会结束此 VM 保存的 Wrangler 授权,但不会删除云资源,也不会让你退出普通的 Dashboard 浏览器会话。
npx wrangler logout
npx wrangler whoami --json
确认结构化结果报告 "loggedIn": false。这个未授权命令可能以非零退出状态结束,这在此处是预期行为。如果只看到连接错误而没有明确的身份验证状态,请在连接恢复后重试。
剩余的本地文件和本地 KV 状态属于这个临时 VM,与已经删除的云资源相互独立。现在可以完成本实验。
总结
你在 Workers KV 中存储了结构化偏好设置和版本元数据,然后通过 Worker 绑定读取它们。你将 Alice 和 Bob 的设置彼此分开,并让缺失、格式错误和不受支持的值返回带有原因说明的默认值。你还区分了存储故障和记录不存在的情况,而不是用同一种响应掩盖两者。
比较本地和云端响应后,你删除了临时 Worker 和命名空间,并退出了登录。下一步,你将为临时通知设置应用层截止时间和 KV 过期时间。



