【问题标题】:What can I do to avoid Syncronous AJAX Request我该怎么做才能避免同步 AJAX 请求
【发布时间】:2018-02-23 15:10:35
【问题描述】:

我有这个数组

var testFlows = ["test1","test2","test3","test4","test5"];

我正在尝试一一获取输入并生成一些 html(生成的 html 并不重要)。

重要的是我想按 testFlows 数组的顺序查看这个 html 面板。我的代码是完全随机的。如果我刷新页面,它们会位于不同的位置。

一种解决方案是制作一个同步 ajax,但它已被弃用且很糟糕,我还能做什么?

代码:

 var testFlows = ["test1","test2","test3","test4","test5"];

  $.each(testFlows, function (index, testFlow) {
            //get the inputs
            $.ajax({
               url: '/flow/getInputs',
               type: 'post',
               data: {testCaseName: testFlow.testCase.name},
               success: function (inputNames) {
                   testCaseAccordion = '<div class="panel panel-default"><div class="panel-heading"><h4 class="panel-title"><a class="collapseTitle" data-toggle="collapse" data-parent="#accordion" href="#collapse-' + testFlow.testCase.name + index + '">' + testFlow.testCase.name + '(' + testFlow.testCase.type.name + ') <span id="eyeIcon" class="fas fa-eye float-right"></span></a></h4></div>';
                   testCaseAccordion += '<div id="collapse-' + testFlow.testCase.name + index + '" class="panel-collapse collapse"><div id="panel-body-' + testFlow.testCase.name + index + '" class="panel-body"></div></div>';
                   $('#accordion').append(testCaseAccordion);
                   if (testFlow.params !== null) {
                       var inputs = testFlow.params.split(',');
                       for (var i = 0; i < inputs.length; i++) {
                           $('#panel-body-' + testFlow.testCase.name + index).append('<strong class="color-red">' + inputNames[i] + ': </strong>' + inputs[i] + '<br>');
                       }
                   }
                   else {
                       $('#panel-body-' + testFlow.testCase.name + index).append("This test case doesn't have any inputs");
                   }
               }
            });

        });

【问题讨论】:

  • 如果我使用async: false, 编写代码,它可以工作。但我不想要那个
  • 在单个请求中发送所有数据(即整个数组),然后根据需要循环遍历从请求返回的数组
  • 我建议使用 Promise。
  • 真的不需要随机加粗你的问题的各个部分,这有点烦人 阅读。
  • 我同意罗里的观点。当你只能发出一个 HTTP 请求时,不要发出 10 个 HTTP 请求,发送一个包含 10 个元素的数组。

标签: javascript jquery ajax


【解决方案1】:

您可以使用承诺,例如,在您的情况下:

var testFlows = ["test1","test2","test3","test4","test5"];

function success(testFlowAndInputNames, index) {
    var testFlow = testFlowAndInputNames[0];
    var inputNames = testFlowAndInputNames[1];
    var testCaseAccordion = '<div class="panel panel-default"><div class="panel-heading"><h4 class="panel-title"><a class="collapseTitle" data-toggle="collapse" data-parent="#accordion" href="#collapse-' + testFlow.testCase.name + index + '">' + testFlow.testCase.name + '(' + testFlow.testCase.type.name + ') <span id="eyeIcon" class="fas fa-eye float-right"></span></a></h4></div>';
    testCaseAccordion += '<div id="collapse-' + testFlow.testCase.name + index + '" class="panel-collapse collapse"><div id="panel-body-' + testFlow.testCase.name + index + '" class="panel-body"></div></div>';
    $('#accordion').append(testCaseAccordion);
    if (testFlow.params !== null) {
        var inputs = testFlow.params.split(',');
        for (var i = 0; i < inputs.length; i++) {
            $('#panel-body-' + testFlow.testCase.name + index).append('<strong class="color-red">' + inputNames[i] + ': </strong>' + inputs[i] + '<br>');
        }
    }
    else {
        $('#panel-body-' + testFlow.testCase.name + index).append("This test case doesn't have any inputs");
    }
}


var arrayOfPromises = testFlows.map(function (testFlow) {
    return new Promise(function (resolve, reject) {
        $.ajax({
            url: '/flow/getInputs',
            type: 'post',
            data: {testCaseName: testFlow.testCase.name},
            success: resolve
        });
    })
    .then(function(inputNames) { 
        return [testFlow, inputNames];
    })
});

Promise.all(arrayOfPromises)
    .then(function(results) {
        results.forEach(success)
    });

【讨论】:

  • 一点也不,promises API 保证在所有请求完成时排序。哪个 Promise.all 可以
  • 我理解你,你把它弄反了,promise 将以随机顺序完成,但 Promise.all 会排序它们。所以渲染是有序的。
  • 你完全正确。我的错。对于那个很抱歉。不过,我仍然建议 OP 提出一个请求。
【解决方案2】:

jQuery ajax 返回一个promise,所以你可以将所有promise 保存到一个数组中,例如:

var testFlows = ["test1", "test2", "test3", "test4", "test5"];

var testFlowsPromises = $.map(testFlows, function(testFlow, index) {
  //get the inputs
  return $.ajax({
    url: '/flow/getInputs',
    type: 'post',
    data: {testCaseName: testFlow.testCase.name}
  }).then(function(inputNames) {
    return {
      inputNames: inputNames,
      testFlow: testFlow
    };
  });
});

然后,等到所有这些都完成:

$.when.apply($, testFlowsPromises).done(function() {
  $.each(arguments, function(index, data) {
    // do stuff with index, data.inputNames, data.testFlow
  });
});

现在您将拥有一个按相同顺序排列的 ajax 数据数组。

演示

https://jsbin.com/fixuxezale/edit?js,console

【讨论】:

  • 我应该把 $.when.apply 放在哪里?在一切之外?
  • 是的,一切都在外面
  • 请注意,这并不能保证响应的顺序,因为 OP 声明是一项要求
  • 你能解释一下吗?完成所有请求后,响应的顺序与发出请求的顺序相同。
  • 在jsbin上添加示例,保证响应顺序。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-03-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-07-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多