如何将读取JSON的XMLHttpRequest代码封装为可主动调用的函数
可主动调用的封装方案
你现有代码已经实现了基础回调式封装,我们可以优化为更通用、无业务绑定的可复用请求函数,同时修复原有代码未判断readyState的逻辑漏洞(会导致回调被多次触发),提供两种常用实现:
1. 回调式封装(兼容你原有调用习惯)
/** * 通用GET请求JSON文件 * @param {string} url 请求地址 * @param {function} callback 回调函数,参数为 (错误信息, 响应数据) */ function getJSON(url, callback) { const ajax = new XMLHttpRequest(); ajax.open('GET', url, true); ajax.responseType = 'json'; ajax.onreadystatechange = function () { // 必须判断请求完成状态 if (ajax.readyState !== 4) return; if (ajax.status === 200) { callback(null, ajax.response); } else { callback(new Error(`请求失败,状态码:${ajax.status}`), ajax.response); } }; // 捕获网络异常 ajax.onerror = function () { callback(new Error('网络请求异常'), null); }; ajax.send(); }
调用示例(实现你原有的业务逻辑):
// 任意位置主动调用即可 getJSON('games.json', function (err, data) { if (err) { console.log('Ocorreu um erro', err); return; } const bets = document.getElementById('bets-description'); bets.innerHTML = ''; bets.textContent = data.types[0].description; // 优先用textContent避免XSS风险 });
2. Promise式封装(更现代,支持async/await调用)
如果项目环境支持ES6,更推荐这种写法,避免回调嵌套问题:
/** * 通用GET请求JSON文件(Promise版) * @param {string} url 请求地址 * @returns {Promise<any>} 响应数据Promise */ function getJSON(url) { return new Promise((resolve, reject) => { const ajax = new XMLHttpRequest(); ajax.open('GET', url, true); ajax.responseType = 'json'; ajax.onreadystatechange = function () { if (ajax.readyState !== 4) return; if (ajax.status === 200) { resolve(ajax.response); } else { reject(new Error(`请求失败,状态码:${ajax.status}`)); } }; ajax.onerror = function () { reject(new Error('网络请求异常')); }; ajax.send(); }); }
调用示例:
// 普通then链式调用 getJSON('games.json') .then(data => { const bets = document.getElementById('bets-description'); bets.innerHTML = ''; bets.textContent = data.types[0].description; }) .catch(err => { console.log('Ocorreu um erro', err); }); // async/await 调用(更简洁) async function loadBetsDescription() { try { const data = await getJSON('games.json'); const bets = document.getElementById('bets-description'); bets.innerHTML = ''; bets.textContent = data.types[0].description; } catch (err) { console.log('Ocorreu um erro', err); } } // 主动触发调用 loadBetsDescription();
内容的提问来源于stack exchange,提问作者Guilherme
相关产品推荐
相关产品推荐

