【问题标题】:How to make ajax synchronous instead of using async:false?如何使 ajax 同步而不是使用 async:false?
【发布时间】:2020-08-05 08:08:03
【问题描述】:

我在使用 ajax 异步时遇到了一些问题。我有一个数组,然后循环遍历数组以进行 ajax 调用,如果成功,ajax 将返回一个 xml 字符串,我将使用它来填写表格并更新进程栏。我使用async:false,它在 Firefox 上运行良好,但在 Chrome 上无法正常运行。我也尝试过使用$.ajax().done(),但完全没有影响。

ajax 调用完成后是否有办法获取响应的 xml 字符串然后运行下一个循环?

for (var i = 0; i <= arr.length; i++){
    $.ajax({
        url: '',
        data: '',
        async: false
    }).done(function(xml) {
       //get xml string to handle and put it into some table as contents
    });
    //Then go to next loop
}

【问题讨论】:

  • 真正同步的 AJAX 已被弃用,这是有充分理由的。任何东西都不应该阻塞 UI 线程。阅读async/awaitawait 通话。注意it still won't be synchronous, and will never be, and you need to adjust the remaining code accordingly.
  • 在此处使用 await 显然不是最理想的:请求 2 对请求 1 没有依赖性,因此以串行方式而不是并行方式运行它们会很慢。
  • 我已经尝试过使用 async/await,它对解决我的问题真的很有帮助。非常感谢@CherryDT

标签: javascript jquery ajax asynchronous


【解决方案1】:

不要试图使异步代码同步。您将锁定事件循环并获得严重的性能损失。

并行发出请求。将 Promise 收集到一个数组中。使用Promise.all 确定它们何时完成所有

然后你就可以从中提取数据,然后做你想做的事。

例如:

const baseUrl = "https://jsonplaceholder.typicode.com/users/";
const userIds = [1,2,3,4,5];

const completeUrls = userIds.map( id => `${baseUrl}${id}` );
const promises = completeUrls.map( url => jQuery.ajax({url}) );
const collectedDataPromise = Promise.all(promises);

collectedDataPromise.then( data => {
    const names = data.map( user => user.name );
    const ul = $("<ul />");
    names.forEach( name => {
       ul.append( $("<li>").text(name) );
    });
    $("body").append(ul);
});
&lt;script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"&gt;&lt;/script&gt;

【讨论】:

  • 要发布的数据不仅包含作为您的示例的 id,它还包含作为参数的 GET 字符串
  • @StevenDang — 正如你所说,这只是一个例子。请求的具体内容无关紧要。
  • 所以如果我尝试这种方式,我就不必再使用for了,对吧?
  • 正确。这使用map 执行迭代(并将结果放入数组中)。
  • 最后,我决定使用 async/await 来解决我上面回答的问题:D
【解决方案2】:

如果您必须在每次迭代中更新数据,您可以使用一些字符串并在 .done() 中更新。

尝试这样的递归:

var counter = arr.length;

function callAjax() {
  if (counter) {
    $.ajax({
      url: '',
      data: ''
    })
    .done(function(xml) {
      //get xml string to handle and put it into some table as contents
      counter--;
      callAjax();
    });
  }
}

【讨论】:

  • 这个问题明确想避免async: false
  • @Quentin 对不起,我粘贴了问题中的 ajax 调用。我更新的代码应该可以异步工作。
【解决方案3】:

最后,我得到了我自己的解决方案,我使用 async/await 才有意义。

async function ajaxGetData(){
    return $.ajax({
               url: '',
               data: ''
          }).then(response => response.data);
}

async function hanldeResponse(){
   var arr = [1,2,...];
   for(var i = 0; i < arr.length; i++){
       let res = await ajaxGetData();
       //some code to handle the response with res variable
   }
}

【讨论】:

    猜你喜欢
    • 2016-04-03
    • 1970-01-01
    • 2017-09-17
    • 2016-02-13
    • 1970-01-01
    • 1970-01-01
    • 2010-10-09
    相关资源
    最近更新 更多