JavaScript函数外部无法访问异步获取的数据问题求助
异步数据访问后无法直接获取属性值
我在处理数据访问时遇到了问题,以下是我的代码片段:
$.each(response.data.tree, function (i) { // 只处理文件类型 if (this.type == 'blob') { // 初始化变量 var link = null, content = null; // 构造文件内容的访问链接 link = 'https://raw.githubusercontent.com/jkulikowski84/Code/main/' + this.path.replace(/ /g, '%20'); let data = []; async function getCode() { // 请求文件内容 const response = await fetch(link); // 转换为文本格式 const data = await response.text(); // 将数据存入数组 addData(link, data); } function addData(link, object) { data['link'] = link; data['code'] = object; } // 调用异步获取数据的函数 getCode(); console.log(data); } });
当我在控制台打印data时,能看到预期的内容,但尝试直接通过console.log(data['code'])或console.log(data['link'])访问时,却返回undefined。请问如何在函数外部直接访问这些code和link数据?
问题原因
核心问题是异步操作的执行顺序:getCode()是异步函数,调用它之后代码会立刻执行console.log(data),此时fetch请求还未完成,addData也还没被调用,data仍是空数组。控制台能看到预期内容是因为浏览器会实时更新对象的预览,但实际代码执行时属性还未被赋值。
解决方案
要在异步操作完成后再访问数据,有两种常用方式:
在数据更新后处理逻辑
把需要使用data的代码放到addData函数内,确保数据准备好后再执行:function addData(link, object) { data['link'] = link; data['code'] = object; // 在这里处理数据,比如打印或渲染到页面 console.log(data['code']); }用
async/await等待异步完成
将$.each的回调改为异步函数,等待getCode执行完毕后再访问数据:$.each(response.data.tree, async function (i) { if (this.type == 'blob') { let link = 'https://raw.githubusercontent.com/jkulikowski84/Code/main/' + this.path.replace(/ /g, '%20'); let data = {}; // 这里用对象更合理,因为存储的是键值对而非数组元素 async function getCode() { const response = await fetch(link); const code = await response.text(); data.link = link; data.code = code; } await getCode(); // 等待异步请求完成 console.log(data.code); // 此时可正常访问属性 } });
2024年6月7日更新:优化后的GitHub仓库搜索实现
经过尝试后,我找到了更高效的实现方式。我的需求是构建一个自定义函数,能够在GitHub仓库中搜索关键词并将对应数据拉取到网站上。最初的代码效率很低,会遍历每个文件并发起超过90次请求。
新代码仅通过1次仓库目录树请求获取所有文件信息,再批量处理文件内容请求,速度更快:
function handle(e) { // 获取当前激活页面 var ActivePage = $('div.page.active'); // 默认显示所有目录内容 ActivePage.find('li.back, li.dir, li.file').css('display', ''); // 获取搜索框输入内容 var Search_Code = (($('div.page.active').find("#Search_Code"))[0]).value; // 配置不区分大小写的全局正则搜索规则 var Search = new RegExp(Search_Code, 'gi'); // 每次搜索前清空旧结果 jQuery('div[class="SearchResults"]').remove(); // 创建搜索结果展示容器 ActivePage.find('li.titles').after($('<div class="SearchResults">')); // 按下回车键且搜索内容不为空时执行搜索 if((e.keyCode === 13) && (Search_Code)) { var _this = this; // 请求仓库完整目录树(递归获取所有文件节点) $.ajax({ url: 'https://api.github.com/repos/jkulikowski84/Code/git/trees/main?recursive=1', type: 'GET', data: {}, dataType: 'jsonp', success: function(response){ // 遍历所有目录节点 $.each(response.data.tree, function(i){ // 只处理文件类型节点 if(this.type == 'blob') { // 构造文件内容的访问链接 var link = "https://raw.githubusercontent.com/jkulikowski84/Code/main/" + (this.path).replace(/ /g,"%20"); // 请求文件内容并匹配关键词 $.ajax({ url: link, type: 'GET', data: {}, dataType: 'text', success: function(response){ // 匹配关键词(文件内容或链接中包含) if ((response).match(Search) || (link).match(Search)) { // 隐藏原始目录,显示搜索结果 ActivePage.find('li.back, li.dir, li.file').css('display', 'none'); // 将匹配的文件链接添加到结果容器 ActivePage.find('div.SearchResults').append($('<li class="SearchResults">' + link + '</li>')); } }, error : function(response){ if(console && console.log) console.log('Request Error:', response); } }); } }); }, error : function(response){ if(console && console.log) console.log('Request Error:', response); } }); } return false; }
内容的提问来源于stack exchange,提问作者Koobah84
相关产品推荐
相关产品推荐

