JavaScript 动态获取 JSON 数据的多种实用方法
在现代 Web 开发中,JSON(JavaScript Object Notation)已成为数据交换的事实标准,无论是从服务器 API 获取数据,还是加载本地的配置文件,我们都需要在 JavaScript 中动态地读取和处理 JSON 数据,本文将详细介绍几种在 JavaScript 中动态获取 JSON 数据的核心方法,从最基础的 fetch API 到更高级的模块化方案,并辅以清晰的代码示例。
核心基础:使用 fetch API (推荐)
fetch API 是现代浏览器中内置的一个强大而简单的接口,用于发起网络请求,它是获取远程 JSON 数据最常用、最标准的方法。
工作原理:
fetch 返回一个 Promise 对象,当服务器响应时,这个 Promise 会 resolved,并返回一个 Response 对象,我们需要调用 response.json() 方法来将响应体解析为 JSON 对象。response.json() 本身也返回一个 Promise。
示例代码:
假设我们有一个远程 JSON 文件 data.json如下:
{
"name": "张三",
"age": 30,
"city": "北京",
"skills": ["JavaScript", "React", "Node.js"]
}
我们可以使用 fetch 来获取它:
// 定义获取数据的异步函数
async function fetchUserData() {
try {
// 1. 发起 fetch 请求
const response = await fetch('data.json');
// 2. 检查请求是否成功
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
// 3. 将响应体解析为 JSON 对象
const userData = await response.json();
// 4. 处理获取到的数据
console.log('成功获取用户数据:', userData);
console.log(`用户姓名: ${userData.name}`);
console.log(`技能列表: ${userData.skills.join(', ')}`);
} catch (error) {
// 5. 捕获并处理错误
console.error('获取数据时出错:', error);
}
}
// 调用函数
fetchUserData();
优点:
- 现代标准:Promise-based,语法简洁,易于使用
async/await。 - 功能强大:支持请求和响应的丰富控制(如设置请求头、方法等)。
- 广泛支持:所有现代浏览器都支持。
传统方法:使用 XMLHttpRequest (XHR)
在 fetch 出现之前,XMLHttpRequest (XHR) 是获取远程数据的主要方式,虽然现在不推荐用于新项目,但在维护旧代码或需要兼容非常古老的浏览器时,你仍然会遇到它。
工作原理:
通过创建一个 XHR 对象,配置请求,然后发送它,你需要监听 onload 事件来处理成功响应,并手动调用 JSON.parse() 来解析数据。
示例代码:
function fetchUserDataWithXHR() {
const xhr = new XMLHttpRequest();
// 配置请求:GET方法,异步请求
xhr.open('GET', 'data.json', true);
// 设置请求头,告诉服务器我们期望接收 JSON 格式的数据
xhr.setRequestHeader('Accept', 'application/json');
// 监听请求完成事件
xhr.onload = function() {
if (xhr.status >= 200 && xhr.status < 300) {
// 手动解析响应文本为 JSON 对象
const userData = JSON.parse(xhr.responseText);
console.log('使用 XHR 成功获取数据:', userData);
} else {
console.error(`请求失败,状态码: ${xhr.status}`);
}
};
// 监听错误事件
xhr.onerror = function() {
console.error('网络请求发生错误');
};
// 发送请求
xhr.send();
}
// 调用函数
fetchUserDataWithXHR();
优点:
- 兼容性好:可以在所有浏览器中工作,包括非常古老的版本。
- 控制力强:可以更细粒度地控制请求的各个阶段。
缺点:
- 回调地狱:容易陷入多层嵌套的回调,代码难以维护。
- API 繁琐:相比
fetch,代码量更大,更冗长。
本地文件加载:使用 <script>
JSON 数据可能就存放在一个本地的 .json 文件中,我们希望直接在网页中加载它,一个巧妙的办法是利用 <script> 标签的 src 属性,因为浏览器会自动解析并执行 JavaScript 文件。
工作原理:
将 JSON 文件作为 JavaScript 模块来加载,但要注意,这种方法要求 JSON 文件必须符合 JavaScript 模块的语法(即使用 export 导出数据),并且需要 type="module" 属性。
步骤:
-
创建
data.json文件,并使用export导出其内容:// data.json export const userData = { "name": "李四", "age": 28, "city": "上海" }; -
在 HTML 中引入并使用:
<!-- index.html --> <!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <title>加载本地 JSON</title> </head> <body> <script type="module"> // 直接导入 JSON 模块 import { userData } from './data.json'; console.log('通过 script 标签加载的数据:', userData); console.log(`用户姓名: ${userData.name}`); </script> </body> </html>
优点:
- 简单直接:无需任何网络请求,加载速度快。
- 模块化:天然支持 ES 模块系统,便于代码组织。
缺点:
- 仅限本地:无法用于从其他域名加载远程数据(受同源策略限制)。
- 依赖环境:要求服务器支持 ES 模块。
动态创建 <script> 标签 (JSONP - 已过时)
在过去,为了解决跨域问题,开发者们使用了一种名为 JSONP (JSON with Padding) 的技巧,它的原理是动态创建 <script> 标签,其 src 指向一个支持 JSONP 的 API 服务器。
注意: JSONP 是一种非常古老且存在安全风险(如 XSS 攻击)的技术。强烈建议在新项目中使用 CORS(跨域资源共享)配合 fetch API,而不是 JSONP,此处仅作知识普及。
工作原理:
- 在页面中定义一个全局回调函数(如
handleResponse)。 - 动态创建一个
<script>标签,将其src设置为 API 地址,并附带一个callback参数,值为回调函数名。 - 服务器收到请求后,会将 JSON 数据包装成
handleResponse({...})这样的形式返回。 - 浏览器执行返回的 JavaScript 代码,从而调用本地的
handleResponse函数并传入数据。
示例代码:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">JSONP 示例 (已过时)</title>
</head>
<body>
<h1>查看控制台输出</h1>
<script>
// 1. 定义全局回调函数
function handleResponse(data) {
console.log('通过 JSONP 获取的数据:', data);
}
// 2. 动态创建 script 标签
function fetchJsonp() {
const script = document.createElement('script');
// 假设服务器支持 callback 参数
script.src = 'https://api.example.com/data?callback=handleResponse';
document.body.appendChild(script);
}
// 3. 调用函数发起请求
fetchJsonp();
</script>
</body>
</html>
总结与最佳实践
| 方法 | 适用场景 | 优点 | 缺点 |
|---|---|---|---|
fetch API |
现代 Web 开发,获取远程数据 | 简洁、基于 Promise、功能强大 | 不支持 IE 浏览器 |
XMLHttpRequest |
维护旧项目、兼容性要求极高 | 兼容性极好 | API 繁琐,易产生回调地狱 |
<script> |
加载本地的 JSON 配置文件 | 加载快,支持模块化 | 仅限本地,依赖 ES 模块环境 |
| JSONP | (不推荐) 解决跨域请求的历史方案 | 可绕过同源策略 | 安全性差,易受攻击,已被 CORS 取代 |
核心建议:



还没有评论,来说两句吧...