如何用JavaScript的fetch()加载所有JSON文件到HTML表格?
问题描述
现有文件结构如下:
/mysite/index.html/mysite/products/文件夹,包含从1.json到578.json的多个JSON文件,每个文件对应单个产品,格式示例:[{"id":1,"name":"16' Tire Japan","stock":145}]/mysite/script.html(与index.html关联)
index.html中包含产品表格:
<table> <thead> <th>id</th> <th>name</th> <th>stock</th> </thead> <tbody id="products"></tbody> </table>
需求:使用JavaScript逐个获取/products/下所有存在的JSON文件,将数据填充到表格的tbody(id为products)中。
之前使用单个products.json文件的实现代码:
fetch("products.json") .then(function(response) { return response.json(); }) .then(function(products){ let placeholder = document.querySelector("#products"); let out = ""; for(let product of products){ out += `<tr id='tr${product.id}'> <td class='id'>${product.id}</td> <td class='name'>${product.name}</td> <td class='stock'>${product.stock}</td> </tr>`; } placeholder.innerHTML = out; });
解决方案
浏览器端JavaScript无法直接遍历服务器上的文件夹,因此可以通过以下两种方式实现:
方式一:按已知ID范围批量请求(适用于ID连续或已知最大ID的情况)
如果已知产品ID的范围(比如1到578),可以循环请求每个ID对应的JSON文件,忽略不存在的文件:
并行请求版本(效率更高)
const tbody = document.querySelector("#products"); const maxProductId = 578; // 替换为实际最大产品ID const fetchTasks = []; // 生成所有请求任务 for (let id = 1; id <= maxProductId; id++) { const task = fetch(`products/${id}.json`) .then(res => { if (!res.ok) throw new Error(`产品${id}不存在`); return res.json(); }) .catch(err => { console.log(err.message); return null; // 标记不存在的产品 }); fetchTasks.push(task); } // 等待所有请求完成后渲染表格 Promise.all(fetchTasks) .then(results => { let tableRows = ""; // 过滤无效结果,将每个JSON的数组转为单个产品对象 const validProducts = results.filter(item => item).flat(); validProducts.forEach(product => { tableRows += ` <tr id='tr${product.id}'> <td class='id'>${product.id}</td> <td class='name'>${product.name}</td> <td class='stock'>${product.stock}</td> </tr> `; }); tbody.innerHTML = tableRows; }) .catch(err => console.error("加载数据失败:", err));
串行请求版本(减少服务器并发压力)
如果担心并发请求过多,可以改用串行请求:
const tbody = document.querySelector("#products"); const maxProductId = 578; let tableRows = ""; async function loadAllProducts() { for (let id = 1; id <= maxProductId; id++) { try { const res = await fetch(`products/${id}.json`); if (!res.ok) throw new Error(); const [product] = await res.json(); // 取出数组中的单个产品对象 tableRows += ` <tr id='tr${product.id}'> <td class='id'>${product.id}</td> <td class='name'>${product.name}</td> <td class='stock'>${product.stock}</td> </tr> `; } catch { console.log(`跳过不存在的产品ID:${id}`); } } tbody.innerHTML = tableRows; } loadAllProducts();
方式二:后端生成文件列表(更高效推荐)
如果有后端支持,建议在服务器端生成一个包含所有存在的产品ID的列表文件(比如products/list.json),内容示例:
[1,2,3,5,7,...,578]
然后先请求这个列表,再根据列表中的ID请求对应的JSON文件,避免无效的404请求:
const tbody = document.querySelector("#products"); fetch("products/list.json") .then(res => res.json()) .then(productIds => { const fetchTasks = productIds.map(id => fetch(`products/${id}.json`).then(res => res.json()) ); return Promise.all(fetchTasks); }) .then(allProducts => { let tableRows = ""; allProducts.flat().forEach(product => { tableRows += ` <tr id='tr${product.id}'> <td class='id'>${product.id}</td> <td class='name'>${product.name}</td> <td class='stock'>${product.stock}</td> </tr> `; }); tbody.innerHTML = tableRows; }) .catch(err => console.error("加载数据失败:", err));
内容的提问来源于stack exchange,提问作者Ирина Комсомольская
相关产品推荐
相关产品推荐

