浏览器的背包:数据获取与存储完全指南

浏览器的隐藏超能力:Web API开发者指南(4部分系列)
欢迎回到我们探索浏览器隐藏超能力的旅程!到目前为止,我们已经学习了为什么Web API是必不可少的(第1部分)以及如何使用DOM API操作页面(第2部分)。我们的应用程序现在是交互式的,但它们有一个问题:它们没有记忆,也无法与外部世界交流。
今天,我们要给我们的浏览器一个背包。这个背包有两个口袋:
一个对讲机,可以与互联网上任何地方的服务器通信。这就是Fetch API
一个笔记本,可以记录信息并在以后记住它。这就是Web Storage API
掌握这两个API将使你的原生JavaScript项目从简单的玩具提升为完整的应用程序。
你的对讲机:Fetch API
多年来,开发者使用一个笨重的工具XMLHttpRequest(通常昵称为"XHR")来发起网络请求。它很强大,但语法复杂且不直观。
Fetch API是它的现代、强大且更清洁的替代品。它基于Promise,这使得处理异步操作(比如等待服务器响应)变得轻而易举。
发起GET请求(获取数据)
让我们从免费的JSONPlaceholder API获取一些用户数据,就像我们在第1部分中预览的那样。
async/await语法是处理Promise最清洁的方式。让我们分解这个过程:
  1. // 一个获取并显示用户的函数
  2. async function fetchUsers() {
  3. const userList = document.querySelector('#user-list');

  4. try {
  5. // 1. "await"服务器的响应
  6. const response = await fetch('https://jsonplaceholder.typicode.com/users');

  7. // 2. 检查响应是否成功(状态码200-299)
  8. if (!response.ok) {
  9. // 如果不成功,抛出错误被catch块捕获
  10. throw new Error(`网络响应不正常: ${response.statusText}`);
  11. }

  12. // 3. 响应体是一个流。我们需要将其解析为JSON。
  13. // 这也是一个异步操作,所以我们需要"await"它。
  14. const users = await response.json();

  15. // 4. 现在我们有了数据!我们可以使用第2部分的DOM技能。
  16. users.forEach(user => {
  17. const li = document.createElement('li');
  18. li.textContent = user.name;
  19. userList.append(li);
  20. });

  21. } catch (error) {
  22. // 如果try块中任何地方出错,都会被这里捕获。
  23. console.error('获取错误:', error);
  24. userList.textContent = '加载用户失败。';
  25. }
  26. }

  27. // 调用函数
  28. fetchUsers();
javascript
就是这样!在几行可读的代码中,我们发起了一个网络请求,处理了潜在的错误,解析了数据,并更新了DOM。不需要任何库。
发起POST请求(发送数据)
那么向服务器发送数据呢?Fetch也能优雅地处理这个。我们只需要传递第二个参数:一个选项对象。
  1. async function createUser(userData) {
  2. try {
  3. const response = await fetch('https://jsonplaceholder.typicode.com/posts', {
  4. method: 'POST', // 指定HTTP方法
  5. headers: {
  6. // 告诉服务器我们正在发送JSON
  7. 'Content-Type': 'application/json'
  8. },
  9. // 我们发送的数据,转换为JSON字符串
  10. body: JSON.stringify(userData)
  11. });

  12. if (!response.ok) {
  13. throw new Error(`HTTP错误!状态: ${response.status}`);
  14. }

  15. const result = await response.json();
  16. console.log('成功创建用户:', result);

  17. } catch (error) {
  18. console.error('创建用户时出错:', error);
  19. }
  20. }

  21. // 使用示例:
  22. const newUser = {
  23. name: 'Jane Doe',
  24. username: 'janedoe99',
  25. email: 'jane@example.com'
  26. };

  27. createUser(newUser);
javascript
你的笔记本:Web Storage API
好的,我们可以获取数据。但如果用户刷新页面怎么办?我们漂亮的用户列表就消失了。我们需要一种在浏览器本身存储信息的方法。
Web Storage API提供了一个简单的、持久的键值存储。它有两种形式。
1. localStorage
localStorage想象成一个永久的笔记本。保存在这里的数据即使在浏览器关闭并重新打开后也会持续存在。它非常适合保存用户设置(比如"暗色模式"偏好)或用于身份验证的JWT令牌。
API非常简单:
localStorage.setItem('key', 'value'): 保存一个值。
localStorage.getItem('key'): 检索一个值。
localStorage.removeItem('key'): 删除一个值。
localStorage.clear(): 删除所有内容。
重要提示: localStorage只能存储字符串。如果你想存储JavaScript对象,必须先用JSON.stringify()将其转换为字符串,检索时用JSON.parse()解析回来。
示例:保存主题偏好。
  1. const themeToggleButton = document.querySelector('#theme-toggle');

  2. // 页面加载时,检查localStorage中是否保存了主题
  3. const savedTheme = localStorage.getItem('theme');
  4. if (savedTheme) {
  5. document.body.classList.add(savedTheme);
  6. }

  7. themeToggleButton.addEventListener('click', () => {
  8. document.body.classList.toggle('dark-mode');

  9. // 切换后,保存当前状态
  10. if (document.body.classList.contains('dark-mode')) {
  11. localStorage.setItem('theme', 'dark-mode');
  12. } else {
  13. localStorage.removeItem('theme'); // 或者设置为'light-mode'
  14. }
  15. });
javascript
2. sessionStorage
sessionStorage就像当前浏览器标签页的便利贴。它与localStorage有完全相同的API(setItemgetItem等),但有一个关键区别:当标签页关闭时,数据会被清除。
它非常适合存储不应该永久存在的临时信息,比如多页面表单的数据或结账前购物车的状态。
未来一瞥:IndexedDB
对于简单的键值对,localStorage是完美的。但如果你需要存储大量结构化数据并高效查询,就像真正的数据库一样呢?为此,浏览器提供了IndexedDB。它是一个完整的、事务性的客户端数据库。它比localStorage复杂得多,但它是构建强大的离线优先应用程序的正确工具。我们不会在这里详细讨论它,但它是你数据存储旅程中的下一个逻辑步骤。
下一步是什么?
我们的应用程序正在变得智能。它可以控制页面(DOM),与服务器通信(Fetch),并记住事情(Web Storage)。它开始感觉像一个真正的应用程序了。
但我们可以进一步推动它。我们可以让它与用户的物理世界互动。
在第4部分中,我们将通过探索设备API来弥合数字与物理的鸿沟。我们将获取用户的位置,弹出系统通知,并与他们的剪贴板互动!
总结
通过掌握Fetch API和Web Storage API,你的浏览器应用程序现在具备了:
网络通信能力:可以与远程服务器进行数据交换
数据持久化:可以在浏览器中保存和检索信息
错误处理:能够优雅地处理网络错误和异常情况
用户体验优化:通过本地存储提供更好的用户体验
这些API是现代Web开发的基础,掌握它们将大大提升你的前端开发能力。