Web-Dev-For-Beginners 浏览器扩展项目实战:“Adopt an API”——选用外部 API 构建带本地存储的浏览器扩展
本篇技术指南围绕 Web-Dev-For-Beginners 仓库“浏览器扩展项目(Part 2)”的配套作业 Adopt an API(日文版见 assignment.ja.md)展开:你将学会如何从公开 API 中选型、规划一个解决真实问题的浏览器扩展,并按“表单输入 + API 集成 + localStorage 持久化 + 异步请求 + 错误处理”的完整规格完成开发与交付。读完之后,你可以直接以仓库内 Carbon Trigger 参考实现为基准,独立完成一个可提交、可评分的 API 驱动型浏览器扩展。
作业定位:从静态表单走向“有记忆、会联网”的扩展
上一课(1-about-browsers)搭建了扩展的骨架与表单界面;本课 README 让扩展“活起来”——接入真实数据并记住用户配置。而 Adopt an API 作业正是这一能力的独立考核:作业要求你自选一个外部 API,构建一个解决真实问题或提供实用功能的浏览器扩展,API 选型可以小到“宠物照片不够看”(例如用 Dog CEO API 随机取狗图),也可以大一些,核心目标是让你独立完成一次完整的 API 集成练习。
这个作业的评分点不是“选了什么 API”,而是五个工程能力的落地程度:API 集成、代码质量、用户体验、Local Storage 使用、文档质量(详见后文完整 Rubric)。因此下文会先给出作业原文的完整规格,再对照仓库参考实现逐条印证。
四步工作流:选 API → 规划 → 构建 → 测试打磨
第一步:选择你的 API
作业给出的选型建议是:从公开免费 API 列表(public-apis,assignment.md 中链接)中挑选。面向初学者的推荐方向包括:
- 娱乐:Dog CEO API——随机狗图片;
- 天气:OpenWeatherMap——当前天气数据;
- 名言:Quotable API——励志语录;
- 新闻:NewsAPI——当前头条;
- 趣味事实:Numbers API——数字冷知识。
选型标准可以从参考项目反推:仓库自己的 Carbon Trigger 扩展选用 CO2 Signal API,只依赖一个 auth-token 请求头加一个 countryCode 查询参数即可取数——无需复杂鉴权、单次请求即得结果的 API 最适合初学者(见“入门提示”第 1 条)。
第二步:写代码前先回答四个规划问题
作业要求在编码前明确回答:
- 你的扩展解决什么问题?
- 目标用户是谁?
- 你会在 local storage 里存什么数据?
- API 失败或触发限流时如何处理?
第 3、4 问直接对应参考实现的行为:solution/src/index.js 只持久化 apiKey 与 region 两个键(第 72–80 行 setUpUser);第 62–67 行的 catch 分支则在请求失败时隐藏 loading、清空结果区并写入友好错误文案——这正是“如何处理 API 失败”的具体答案。
第三步:构建扩展(功能与代码双规格)
必需功能(Required Features),逐条来自 assignment.md:
- 表单输入所有必需的 API 参数;
- API 集成并具备适当的错误处理;
- 用 local storage 保存用户偏好或 API key;
- 简洁、响应式的用户界面;
- 加载状态与用户反馈。
代码要求(Code Requirements):
- 使用现代 JavaScript(ES6+)特性;
- API 调用使用
async/await; - 用
try/catch做规范错误处理; - 添加解释代码的有意义注释;
- 保持统一的代码格式。
第四步:测试与打磨:
- 用多种输入测试扩展;
- 处理边界情况(断网、非法 API 响应);
- 确保扩展在浏览器重启后仍正常工作(这验证 localStorage 持久化,而不是内存状态);
- 添加用户友好的错误提示。
加分挑战(Bonus Challenges)
作业列出的进阶方向:
- 接入多个 API 端点,扩展功能丰富度;
- 实现数据缓存,减少 API 调用;
- 为常用操作添加键盘快捷键;
- 添加数据导出/导入功能;
- 实现用户自定义选项。
这些挑战与主课 README 中的 GitHub Copilot Agent Challenge 呼应(重试退避、输入校验、带过期时间戳的缓存等),可作为交付后的迭代路线。
参考实现对照:Carbon Trigger 如何逐条满足规格
仓库提供了两版对照代码:start/src/index.js 是带编号占位符(//1 到 //6)的骨架,solution/src/index.js 是完整实现。两者结构一致,适合逐段比对学习。
1. DOM 引用与事件监听:表单规格的落点
参考实现先集中捕获所有表单与结果元素(solution/src/index.js#L3-L15):.form-data 表单、.region-name 与 .api-key 输入框、.errors、.loading、.result-container、.carbon-usage、.fossil-fuel、.my-region、.clear-btn。文件末尾(第 125–129 行)注册监听并启动应用:
form.addEventListener('submit', (e) => handleSubmit(e));
clearBtn.addEventListener('click', (e) => reset(e));
//start app
init();
handleSubmit 首先 e.preventDefault() 阻止页面刷新,再把输入值交给 setUpUser(第 82–86 行)——对应规格中“表单输入 API 参数”的要求。
2. Local Storage:持久化用户偏好
setUpUser 与 init(solution/src/index.js#L88-L123)实现了“记住设置、重启可用”:
// set up api key and region
const setUpUser = async (apiKey, region) => {
localStorage.setItem('apiKey', apiKey);
localStorage.setItem('region', region);
loading.style.display = 'block';
errors.textContent = '';
clearBtn.style.display = 'block';
//make initial call
displayCarbonUsage(apiKey, region);
};
init() 在每次加载时检查 localStorage.getItem('apiKey') 与 localStorage.getItem('region'):任一为 null 视为新用户,显示设置表单;否则隐藏表单、自动用已存凭据发起 API 调用并显示结果与清除按钮。reset() 只移除 region 键后重新 init()。这正是“浏览器重启后仍正常工作”这条测试项的实现依据。查看存储内容的方式:打开开发者工具(F12)→ Application 标签 → Local Storage 展开查看(见前文本地存储面板截图)。
⚠️ 与主课 README 相同的安全提示:把 API key 存在 localStorage 中,任何同页面 JavaScript 都可读取,仅适合学习场景;生产环境应改用服务端安全存储。
3. API 集成与错误处理:CO2 Signal 的完整调用链
参考实现用 axios 调用 CO2 Signal 的 v1/latest 端点(solution/src/index.js#L34-L68):params 携带 countryCode,请求头携带 auth-token 完成鉴权;拿到响应后先校验关键字段(carbonIntensity 与 fossilFuelPercentage 缺失则主动抛错),再 Math.floor 取整、更新 .my-region / .carbon-usage / .fossil-fuel 三个结果区,并隐藏 loading 与表单;catch 分支统一降级为友好提示:
} catch (error) {
console.warn('Data fetch failed:', error.message);
loading.style.display = 'none';
results.style.display = 'none';
errors.textContent = 'Sorry, data unavailable for the selected region.';
}
主课 README 中还给出了零依赖的 fetch 等价写法(async 函数 + try/catch + response.ok 检查 + response.json() 解析),如果选择无构建依赖的 API(如 Dog CEO 这类免 key 接口),照该模式改写即可满足“API 集成 + 错误处理 + 加载状态”三项要求。
从源码结构看,displayCarbonUsage 内还会调用 calculateColor(CO2)(第 50 行),按碳强度值在 [0, 150, 600, 750, 800] 刻度中取最近档位映射到颜色,再通过 chrome.runtime.sendMessage({ action: 'updateIcon', ... }) 更新工具栏图标——这是下一课“动态图标”功能的预埋点,属于扩展而非本作业必需项。
评分 Rubric:交付物的五个维度
assignment.md 给出的完整评分表(90–100% 为模範级):
| 维度 | 模範(90–100%) | 胜任(80–89%) | 发展中(70–79%) | 起步(60–69%) |
|---|---|---|---|---|
| API 集成 | 集成无瑕疵,错误处理与边界情况管理全面 | 集成成功,具备基础错误处理 | 可用但错误处理有限 | 集成存在重大问题 |
| 代码质量 | 干净、注释良好的现代 JS,遵循最佳实践 | 结构良好,注释适度 | 能运行但组织欠佳 | 质量差,注释极少 |
| 用户体验 | 界面精致,加载状态与用户反馈出色 | 界面良好,具备基础反馈 | 基本可用 | 体验差、界面令人困惑 |
| Local Storage | 运用娴熟,含数据校验与管理 | 关键功能正确实现 | 基础实现 | 使用极少或错误 |
| 文档 | 完备 README,含安装步骤与截图 | 覆盖大部分要求的文档 | 缺少部分细节的基础文档 | 文档差或完全缺失 |
对照该表,参考实现可以逐条定位证据:错误处理在 displayCarbonUsage 的 catch 分支;加载状态在 setUpUser/init 中对 .loading 的显隐切换;localStorage 管理在 init/reset 的读-写-删闭环;代码注释则遍布 solution/src/index.js 各函数。
交付清单与入门提示
提交要求(Submission Requirements):
- 一个可运行的浏览器扩展,成功集成为你所选的 API;
- 一份 README,说明:选择了哪个 API 及原因、如何安装与使用、是否需要 API key 或其他前置配置、扩展运行截图;
- 干净、注释充分的代码,遵循现代 JavaScript 实践。
入门提示(Getting Started Tips),共 5 条:
- 从简单开始:选不需要复杂鉴权的 API;
- 读文档:吃透所选 API 的端点与响应结构;
- 先规划 UI:编码前草图化扩展界面;
- 频繁测试:增量构建,每加一个功能就测一次;
- 默认会失败:始终假设 API 调用可能失败并提前规划。
本地运行:从仓库参考项目到浏览器加载
仓库的 start 目录给出了可复现的运行路径(package.json 声明 node >=18.0.0、npm >=9.0.0):
npm install
npm run build
构建脚本即 package.json 中的 webpack(开发时可用 npm run watch 增量构建)。在 Edge/Chrome 中:扩展面板 → Load Unpacked → 选择构建产物 dist 目录即可加载;输入 CO2 Signal 的 API key(通过邮件在 co2signal.com 获取)与你的地区代码(参考 start/README.md 中给出的 Electricity Map 地区代码查询接口,如 US-NEISO),提交后工具栏圆点颜色即反映该地区电网碳强度。你也可以完全跳过参考项目,按“Adopt an API”的作业规格自选 API 从零实现——这正是作业考核的目标能力。
小结
- 作业主体是 Adopt an API:四步流程(选 API → 规划 → 构建 → 测试打磨)+ 加分挑战 + 三件套交付(可运行扩展、README、规范代码)+ 五维 Rubric;
- 必备技术清单:表单输入 API 参数、
async/await+try/catch的 API 集成、localStorage 持久化偏好/key、响应式 UI、加载状态与友好错误提示; - 仓库佐证:start/src/index.js 的六段骨架与 solution/src/index.js 的完整实现(
init/reset/setUpUser/displayCarbonUsage/calculateColor)构成可逐段对照的参考答案; - 教学主线见 5-browser-extension/2-forms-browsers-local-storage/README.md,其中还列有 Geolocation、Notification、Web Storage 等浏览器内置 API 的课后挑战,可作为 API 选型后的第二成长路径。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0624
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00


