如何将多个AJAX请求的翻译结果合并为单一输出?
解决AJAX异步请求合并结果弹窗的问题
问题背景
我主要使用Python,JavaScript经验比较少,最近在做一个网页字段翻译的工具:需要抓取页面上的多个指定字段,调用翻译API后,把结果合并成如下格式统一弹窗输出:
NOT AN OFFICIAL TRANSLATION. FOR REFERENCE USE ONLY. Field_Name: Translation Field_Name2: Translation Field_Name3: Translation
目前代码完成了85%-90%,已经能成功获取字段名、文本,调用翻译API拿到结果,但受AJAX异步特性影响,现在每个翻译结果会单独弹窗,没法合并成一个弹窗输出。我尝试过在AJAX请求内调用函数,但想知道更优的实现方式。
初始代码问题分析
初始代码的核心问题在于:循环发起AJAX请求时,每个请求都是异步执行的,请求完成后直接弹窗结果,没有等待所有请求都完成再合并数据。另外,循环内用var声明变量会导致作用域问题,回调里引用的变量最后都会变成循环的最后一个值。
优化后的解决方案
在Andrew的帮助下,我调整了代码逻辑,解决了异步合并的问题,关键改进点:
- 新增
completedRequests计数器,用来跟踪所有AJAX请求的完成状态 - 把每个请求的翻译结果存入
outputdata数组,统一收集数据 - 使用
let声明循环内的变量,避免异步回调中的变量引用错误 - 在AJAX的
complete回调中判断是否所有请求都已完成,完成后再调用函数合并并弹窗结果
初始代码
//Gathers all the field names and text associated with them. $(document).ready(function() { var allSpans = document.getElementsByTagName('span'); var spanlist = []; var x = 0; var ajax_data = []; var fieldlabels = []; [].slice.call(allSpans).forEach(function(span) { if(span.className === 'readonlyfield') { if(span.textContent) { var spanobject = {}; var textfrom = 'en'; var textto = 'it'; var text = span.innerText; var parentelem = document.getElementById(span.parentNode.id); var parenttext = parentelem.innerText; fieldlabels.push(parenttext + ': '); spanobject.parentfield = span.parentNode.id; spanobject.parenttext = parenttext; spanobject.textfrom = textfrom; spanobject.textto = textto; spanobject.text = text; spanlist.push(spanobject); x++; } } }); var translatebutton = document.createElement('button'); translatebutton.setAttribute("id", x); translatebutton.innerText = 'Translate!'; document.body.appendChild(translatebutton); var finaloutput = "FOR REFERENCE USAGE ONLY. NOT AN OFFICIAL TRANSLATION." + '\n'; // On button click translate all text gathered and alert the final output. $("button").click(function(){ var outputdata = []; for(var i = 0, len = spanlist.length; i < len ; i++){ var textfrom = spanlist[i].textfrom; var textto = spanlist[i].textto; var text = spanlist[i].text; var urlservice = 'MYTRANSLATIONURL==&text='+text+'&textfrom='+textfrom+'&textto='+textto; jQuery.support.cors = true; $.ajax({ url: urlservice, type: 'GET', contentType: "text/html", success: function (data) { getsomedata(data); }, error: function (x, y, z) { alert(x + '\n' + y + '\n' + z); } }); function getsomedata(data) { alert(data); // The code below does not work, I was experimenting with an idea. // ajax_data.push(data + '\n'); } // var temp = fieldlabels.concat(ajax_data); // temp.toString(); }; }); });
最终解决代码
$(document).ready(function() { var allSpans = document.getElementsByTagName('span'); var spanlist = []; var x = 0; [].slice.call(allSpans).forEach(function(span) { if(span.className === 'readonlyfield') { if(span.textContent) { var spanobject = {}; var textfrom = 'en'; var textto = 'it'; var text = span.innerText; var parentelem = span.parentNode.id; //REGEX to find field captions in my particular system. var captionID = parentelem.replace(/((TD))?/, "TDCAP"); var captionelem = document.getElementById(captionID); var caption = captionelem.innerText; spanobject.spanparent = span.parentNode.id; spanobject.captionfield = captionelem; spanobject.caption = caption; spanobject.textfrom = textfrom; spanobject.textto = textto; spanobject.text = text; spanlist.push(spanobject); x++; } } }); var translatebutton = document.createElement('button'); translatebutton.setAttribute("id", x); translatebutton.innerText = 'Translate!'; document.body.appendChild(translatebutton); var finaloutput = "FOR REFERENCE USAGE ONLY. NOT AN OFFICIAL TRANSLATION." + '\n'; $("button").click(function(){ var outputdata = []; var completedRequests = 0; var len = spanlist.length; for(var i = 0; i < len ; i++){ var textfrom = spanlist[i].textfrom; var textto = spanlist[i].textto; var text = spanlist[i].text; let parentLet = spanlist[i].spanparent; let textLet = spanlist[i].text; let captionfield = spanlist[i].captionfield; let caption = spanlist[i].caption; var urlservice = 'MYTRANSLATIONURL==&text='+text+'&textfrom='+textfrom+'&textto='+textto; jQuery.support.cors = true; $.ajax({ url: urlservice, type: 'GET', contentType: "text/html", success: function (data) { datastring = caption + ": " + data; outputdata.push(datastring); }, error: function (x, y, z) { alert(x + '\n' + y + '\n' + z); }, complete: function() { if (++completedRequests >= len) { getsomedata(outputdata); } } }); function getsomedata(data) { var finaldata = data.join("\n\n"); final = finaloutput + '\n' + finaldata; alert(final); } }; }); });
内容的提问来源于stack exchange,提问作者Calvin Ellington
相关产品推荐
相关产品推荐

