使用Giphy API上传GIF出现重复请求与重复存储ID问题求助
问题描述
使用Giphy API实现GIF上传并将返回ID存入localStorage时,首次上传功能正常,但后续每次上传都会发起多次请求,且localStorage中会为每个GIF存入多个ID。
原始代码
HTML
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Document</title> </head> <body> <form> <input type="file" /> <input type="submit" /> </form> <div class="tree"></div> <script src="./fetch-api.js"></script> </body> </html>
JavaScript
const form = document.querySelector('form'); const inputFlie = document.querySelector('input'); const preview = document.querySelector('.tree'); const apiKey = 'yourapikeyhere' form.addEventListener('change', () => { const uploadFile = new FormData(); uploadFile.append('file', inputFlie.files[0]); const heads = { method: 'POST', api_key: apiKey , body: uploadFile, }; form.addEventListener('submit', async (event) => { event.preventDefault(); try { const send = await fetch( `https://upload.giphy.com/v1/gifs?api_key=${apiKey}`, heads ); const feedback = await send.json(); if (feedback.meta.status === 200) { form.reset(); uploadID = feedback.data.id; } if (localStorage.getItem('uploaded') === null) { //if we don't create an empty array uploadedGifs = []; uploadedGifs.push(uploadID); localStorage.setItem('uploaded', JSON.stringify(uploadedGifs)); } else { const currentItems = JSON.parse(localStorage.getItem('uploaded')); currentItems.push(uploadID); localStorage.setItem('uploaded', JSON.stringify(currentItems)); } console.log(feedback); } catch (error) { console.log(error); statusMesage.textContent = 'Something went wrong!'; } }); });
问题原因
核心问题是事件监听嵌套绑定:每次选择文件触发change事件时,都会给表单新增一个submit事件监听器。第一次选文件加1个监听器,第二次选文件再加1个,以此类推。后续点击提交时,所有已绑定的submit监听器都会触发,导致多次请求上传,同时多次往localStorage存入同一个ID。
另外还有两个小问题:
uploadID和uploadedGifs未声明,会成为全局变量,可能引发意外问题。FormData在change事件中创建,逻辑上不合理,若用户重复选择文件后提交,可能出现数据不一致的情况。
修复方案
将submit事件监听器移到change事件外部,同时调整FormData的创建时机到submit内部,确保每次提交都使用最新的文件,并且只绑定一次提交事件。
修改后的JavaScript代码:
const form = document.querySelector('form'); const inputFile = document.querySelector('input[type="file"]'); // 更精准的选择器 const preview = document.querySelector('.tree'); const apiKey = 'yourapikeyhere'; // 只绑定一次submit事件 form.addEventListener('submit', async (event) => { event.preventDefault(); // 先判断是否选择了文件 if (!inputFile.files.length) return; const uploadFile = new FormData(); uploadFile.append('file', inputFile.files[0]); const options = { method: 'POST', body: uploadFile, // 注意:api_key只需放在URL参数中,无需在请求配置里设置 }; try { const send = await fetch( `https://upload.giphy.com/v1/gifs?api_key=${apiKey}`, options ); const feedback = await send.json(); if (feedback.meta.status === 200) { form.reset(); const uploadID = feedback.data.id; // 简化localStorage逻辑 const uploadedGifs = JSON.parse(localStorage.getItem('uploaded')) || []; uploadedGifs.push(uploadID); localStorage.setItem('uploaded', JSON.stringify(uploadedGifs)); } console.log(feedback); } catch (error) { console.log(error); // 注意:需提前定义statusMessage元素,否则会报错 // statusMessage.textContent = '上传出错!'; } });
关键修改点
- 移除
change事件监听,直接在submit事件中处理文件获取和上传,避免重复绑定提交监听器。 - 给
uploadID添加const声明,避免全局变量污染。 - 简化localStorage逻辑:使用
JSON.parse(...) || []替代条件判断,代码更简洁。 - 修正请求配置:Giphy API的
api_key只需要放在URL参数中,原代码中的api_key配置项无效。 - 增加文件选择判断,避免用户未选文件就提交的无效请求。
内容的提问来源于stack exchange,提问作者Teodor Angelov
相关产品推荐
相关产品推荐

