首页 / 资讯中心 / 文章详情

Working with Data APIs 课程研读:用 fetch()、Promise 与 async/await 加载网络数据

Working with Data  APIs 课程研读:用 fetch()、Promise 与 async/await 加载网络数据 ★ FEATURED ARTICLE
教程文档示例工程【免费下载链接】website-archiveArchive of the Coding Train website (first version)项目地址https://gitcode.com/gh_mirrors/we/website-archive点击查看免费下载导读本篇文章基于 Coding Train「Working with Data APIs」课程第 1.1 节_Courses/data-and-apis/1.1-fetch.md展开该节是全课程第一个实战项目「纯客户端数据加载」的开篇只用浏览器端的 Webfetch()API 从网络加载文本与图片数据并重点掌握异步事件的处理方式——Promise 与 async/await。读完本文你将掌握fetch()的基本调用姿势、Promise 链式写法、自己封装 Promise、用async/await重构异步代码以及用Promise.all并行发起多个请求的完整实战方案并可对照仓库中的 p5.js 示例代码逐行验证。课程背景与本节定位根据课程总览 index.md本课程面向希望在 Web 应用中处理数据的开发者围绕三个数据项目展开教学纯客户端项目Client-side only用fetch()加载数据并呈现在网页上学习用 Promise 处理异步事件既渲染到 DOM也用 p5.js 绘制到 HTML5 Canvas第二、第三个项目引入 Node.js 服务端编程涉及数据持久化与 API 认证。第 1.1 节正是第一个项目的起点。文档 1.1-fetch.md 明确指出本节内容为This video is client-side only and covers the web fetch() API, loading image data and focusing on handling asynchronous events with Promises (async / await).翻译过来即本节仅涉及客户端覆盖 Web 标准fetch()API、加载图片数据并把重心放在使用 Promiseasync/await处理异步事件上。因此整篇文章都不涉及 Node.js 服务端也不涉及数据库写入运行环境就是「浏览器 本地静态服务器」。学习本节的前置条件课程第 0.2 节 0.2-Setup.md 列出了开始本课程前的准备清单需要掌握的基础知识JavaScript核心HTML 基础CSS 基础有用但非必需需要准备的工具代码编辑器文档示例以 VS Code 为主也提到 Atom、Brackets、Sublime Text 等Shell 访问能力Module 2 服务端部分会用到可以直接运行 p5.js 的在线环境p5.js Web Editor、CodePen、JSFiddle 等由于fetch()是浏览器原生 API本地用静态服务器如 VS Code Live Server打开 HTML 页面即可运行无需安装任何依赖包。先用 p5.js 的 loadJSON 感受「加载数据」这件事在进入fetch()之前先看仓库中 p5.js 教程第 10 章的旧式写法便于理解异步加载的本质。示例 10.05_p5.js_Working_With_APIs/sketch.js 展示了用 p5.js 的loadJSON()从 OpenWeatherMap API 加载伦敦天气数据var weather; function setup() { createCanvas(400, 200); loadJSON( https://api.openweathermap.org/data/2.5/weather?qLondonAPPID001b0f58045147663b1ea518d34d88b4, gotData ); } function gotData(data) { weather data; } function draw() { background(0); if (weather) { fill(255); ellipse(100, 100, weather.main.temp, weather.main.temp); ellipse(300, 100, weather.main.humidity, weather.main.humidity); } }loadJSON(url, callback)采用回调函数模式数据加载完成后调用gotData把结果存进全局变量weather然后在draw()中判断weather是否已就绪再绘制。这种「请求发出后不知道何时返回、靠回调接收结果」的模式正是异步编程的经典形态也是本节要讨论的核心问题。fetch() 基础浏览器原生的数据加载 APIfetch()是浏览器内置的 Web API返回一个Promise替代了旧的XMLHttpRequest。其典型调用链为fetch(url) .then(response response.json()) .then(json { // 拿到解析后的数据做你想做的事 }) .catch(err console.log(err));仓库中对应本节的完整示例位于 Tutorials/P5JS/16_promises/11_promises/sketch.js它演示了「用 Wordnik API 随机取一个单词再用 Giphy API 搜索对应 GIF 并显示图片」的经典流程const wordnikAPI https://api.wordnik.com/v4/words.json/randomWord?minLength5maxLength-1api_key48dd829661f515d5abc0d03197a00582e888cc7da2484d5c7; const giphyAPI https://api.giphy.com/v1/gifs/search?ratingPGapi_keydc6zaTOxFJmzCq; function setup() { noCanvas(); fetch(wordnikAPI) .then(response response.json()) .then(json { createP(json.word); return fetch(giphyAPI json.word); }) .then(response response.json()) .then(json { createImg(json.data[0].images[fixed_height_small].url); }) .catch(err console.log(err)); }这段代码值得逐行拆解步骤代码作用1fetch(wordnikAPI)发起 HTTP GET 请求返回 Promise2.then(response response.json())第一个then拿到Response对象调用.json()解析响应体再次返回一个 Promise3.then(json { createP(json.word); return fetch(giphyAPI json.word); })拿到 Wordnik 返回的 JSON用 p5.js 的createP()把单词渲染到 DOM同时发起第二个fetch()请求并把它作为返回值传递下去4.then(response response.json())第二个then处理第二个请求的响应5.then(json createImg(...))从 Giphy JSON 中取出data[0].images[fixed_height_small].url用createImg()把图片插入页面6.catch(err console.log(err))链中任何一环出错都会跳到catch关键点return fetch(...)让 Promise 链得以延续。在.then()中返回一个新 Promise外层链就会等待它完成后再执行下一个.then()。这是串联多个异步请求的标准手法也是本节「加载图片数据」的实现基础——先请求文本单词再依据文本发起图片请求。Promise 的本质自己动手封装一个 Promise理解了消费 Promise再看如何创建 Promise。仓库示例 Tutorials/P5JS/16_promises/12_promises_make_your_own/sketch.js 完整展示了 Promise 构造器的用法function setup() { noCanvas(); delayES8(1000) .then(() createP(hello)) .catch(err console.error(err)); } async function delayES8(time) { // This function returns a promise! await delay(time); await someThingElse(); let val await somethingElseElse(); return val; } function delay(time) { return new Promise((resolve, reject) { if (isNaN(time)) { reject(new Error(delay requires a valid number.)); } else { setTimeout(resolve, time); } }); }delay(time)是一个自己创建的 Promisenew Promise((resolve, reject) {...})Promise 构造器接收一个执行器函数两个参数分别是成功回调resolve和失败回调reject若传入的time不是数字isNaN为真调用reject(new Error(...))此时外层链会跳到.catch()否则用setTimeout(resolve, time)在time毫秒后触发resolvePromise 进入 fulfilled 状态。这解释了fetch()的内部原理浏览器在完成网络响应后调用resolve网络失败时调用reject使用者只需通过.then/.catch或async/await接住结果即可。用 async/await 重写让异步代码读起来像同步Promise 链写多了会出现回调嵌套与链式缩进async/await语法糖能把同样的逻辑写得像同步代码。仓库示例 Tutorials/P5JS/16_promises/13_16_async_await/sketch.js 给出了与前述 Promise 链等价、但更清晰的 async/await 版本async function wordGIF(num) { const response1 await fetch( ${wordnikAPI}minLength${num}maxLength${num} ); const json1 await response1.json(); const response2 await fetch(giphyAPI json1.word); const json2 await response2.json(); let img_url null; try { img_url json2.data[0].images[fixed_height_small].url; } catch (err) { console.log(no image found for json1.word); console.error(err); } return { word: json1.word, img: img_url }; }使用要点函数必须声明为async function内部才能使用awaitawait fetch(...)会暂停函数执行直到 Promise 完成并返回Responseawait response1.json()再等待 JSON 解析完成await只能等待 Promise如果被 await 的 Promise 被 reject会抛出异常需用try/catch捕获——示例中对「Giphy 搜索不到图片」的情况就用了try/catch兜底避免json2.data[0]越界导致整个应用崩溃async 函数本身也返回 Promise所以可以被.then()消费也可以被其他 async 函数await。对比同一份功能的三段式演进回调 → Promise 链 → async/await可以看到async/await版本缩进更浅、错误处理更直观这也是现代 JavaScript 数据加载的主流写法。并行请求用 Promise.all 同时发起多个 fetch课程第 3.2 节3.2-open-air-quality.md把Promise.all列为独立学习主题而 1.1 节的示例代码里已经用到了它。在 13_16_async_await/sketch.js 中let promises []; for (let i 2; i 10; i) { promises.push(wordGIF(i)); } Promise.all(promises) .then(results { for (let i 0; i results.length; i) { createP(results[i].word); if (results[i].img ! null) { createImg(results[i].img); } } }) .catch(err console.log(err));wordGIF(num)每次根据minLength/maxLength请求指定长度的单词长度 298 个请求全部并行发出Promise.all([...])接收一个 Promise 数组全部 resolve 后才进入.then()results是每个 Promise 返回值的数组顺序与传入数组一致任意一个 Promise reject整体进入.catch()返回对象{ word, img }中img可能为null搜索不到 GIF 时渲染时用if (results[i].img ! null)判断后再创建图片元素。浏览器端的限制与后续课程走向本节限定在客户端运行有两个需要留意的约束跨域CORSfetch()请求第三方 API 时目标服务器必须返回允许跨域的响应头否则浏览器会拦截响应。Wordnik、Giphy 这类公开 API 均开放了 CORS因此可作为教学示例API Key 暴露客户端代码中的api_key任何人通过浏览器开发者工具都能看到只能用于学习演示。课程第 3.4 节3.4-hiding-api-key.md会专门讲解如何通过 Node.js 服务端隐藏 API Key——这正是后续项目引入服务端的原因之一。本节的纯客户端数据加载能力在课程后续小节中会不断复用第 1.2 节 1.2-tabular-data.md用fetch()加载并解析 CSV 表格数据第 1.4 节 1.4-json.md从 API 加载 JSON 并更新 DOM 元素以 ISS 空间站位置接口 wheretheiss.at 为例第 2.3 节 2.3-fetch-post.md从客户端向服务器发送 HTTP POST 请求展示fetch()在客户端—服务器通信中的完整形态。本节配套示例小结为便于复习将本节涉及的仓库源码与对应能力整理如下能力点仓库示例文件核心代码fetch() Promise 链Tutorials/P5JS/16_promises/11_promises/sketch.jsfetch(url).then(r r.json())...自己创建 PromiseTutorials/P5JS/16_promises/12_promises_make_your_own/sketch.jsnew Promise((resolve, reject) {...})async/await Promise.allTutorials/P5JS/16_promises/13_16_async_await/sketch.jsasync functionawaitPromise.allp5.js 回调式加载对照Tutorials/P5JS/p5.js/10/10.05_p5.js_Working_With_APIs/sketch.jsloadJSON(url, gotData)运行方式复制任一示例目录下的index.html与sketch.js用静态服务器如 VS Code Live Server打开index.html即可示例页面通过 CDN 引入 p5.js无需本地安装任何依赖。需要注意示例代码中的 API Key 为教程演示所用实际开发请申请自己的密钥。结语第 1.1 节用「先取单词、再取 GIF」的小项目把 Web 数据加载的三块核心拼图串在了一起fetch()负责发起网络请求Promise 负责编排异步流程async/await让编排更可读。理解了这三者你就掌握了纯客户端数据应用的骨架也为后续学习 CSV 解析、JSON 渲染、乃至 Node.js 全栈开发打下了基础。赞分享教程文档示例工程【免费下载链接】website-archiveArchive of the Coding Train website (first version)项目地址https://gitcode.com/gh_mirrors/we/website-archive点击查看免费下载相关推荐Web-Dev-For-Beginners 银行应用第三课实战基于 Fetch API 与 async/await 的动态数据加载与 DOM 渲染Web Dev For Beginners 银行应用第三课实战基于 Fetch API 与 async/await 的动态数据加载与 DOM 渲染 本篇文章对文档教程前端Eidos异步编程Promise与Async/AwaitEidos异步编程Promise与Async/Await 概述 Eidos作为一款离线的个人数据管理框架在处理大量本地数据操作、SQLite数据库交互、文件ReMe Claude Code 插件安装教程三步开启 MCP 召回与自动会话记录ReMe Claude Code 插件安装教程三步开启 MCP 召回与自动会话记录 ReMe 是一个文件原生的 AI Agent 长期记忆管理工具包Reme人工智能Agent 记忆知识库RAGMCP 服务上一篇Nex-N2.5-Pro多模态输入指南图像与视频处理参数全解析——从patch_size到768帧视频抽帧下一篇开放原子开放硬件许可证详解源师兄V1硬件开源规范与生态贡献指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
阅读完成 · 觉得有帮助?
咨询建站