【问题标题】:jquery synchronous ajax only appends to html at end of loop [duplicate]jquery同步ajax仅在循环结束时附加到html [重复]
【发布时间】:2018-08-08 14:11:05
【问题描述】:

我需要多次运行 php 脚本,但需要使用唯一的 ID。 该脚本每次运行需要 +- 5 秒(将一些文件下载到服务器等..) 首先,我使用 ajax 调用来执行此操作,但问题是这需要按顺序进行,并且使用默认的 ajax 设置同时运行多个实例会产生奇怪的事情。 我将参数 'async' 更改为 'false' 解决了这个问题,因为现在 javascript 在开始下一次迭代之前等待脚本完成。

控制台警报每 5-6 秒弹出一次,我提醒每个帖子的数据,循环等待我点击警报(好)。

我尝试将数据附加到 div 而不是提醒,而是仅在所有迭代完成后才附加。

为什么?

    	 var arr = ["10","20","30"];
       
        $("button").click(function(){
        	$.each(arr, function( index, value ) {
    	 		 console.log( index + ": " + value );
    	 		 $.ajax({
    		        url: "import_xml_single_post.php",
    		        type: "post",
    		        data: {'import_id' : value},
    		        async: false,
    		        success: function(data){
    		        	$( "#result" ).append( data );
    			     	//alert(data);
    			    }     
    		    });
      });
<body>
<button>Click me</button>
<div id="result"></div>
</body>

【问题讨论】:

  • 问题完全是由async: false引起的。浏览器实际上会向您显示有关其使用的警告,这是一种不好的做法。相反,从前一个回调中进行下一个 AJAX 调用。递归是理想的选择。更好的是,*不要像这样打多个电话。它只是不必要地淹没服务器。修改服务器端逻辑使用的模式,并在单个请求中发送所有数据。
  • 不要使用同步 ajax 调用,如果您需要确保 ajax 仅在其他 ajax 结束后执行,您应该存储回调并仅在其他 ajax 完成后调用它们

标签: javascript jquery ajax


【解决方案1】:

这是因为浏览器的 UI 线程被 ajax 请求占用,所以浏览器没有机会重新绘制页面。这就是为什么要避免使用同步 ajax 的原因之一。

这些请求无需同步。如果您希望它们串行完成(而不是并行),只需在完成前一个请求时触发后续请求:

var arr = ["10", "20", "30"];

$("button").click(function() {
    var index = 0;
    // Start the process
    doOne();
    function doOne() {
        // Get this value
        var value = arr[index++];
        console.log(index + ": " + value);
        $.ajax({
            url: "import_xml_single_post.php",
            type: "post",
            data: {
                'import_id': value
            },
            success: function(data) {
                $("#result").append(data);
            },
            complete: function() {
                // Kick off the next request
                if (index < arr.length) {
                    doOne();
                }
            }
        });
    }
});

在尖端环境(或使用转译)中,您可以使用async function,这样您就可以编写异步运行的同步代码:

var arr = ["10", "20", "30"];

$("button").click(async function() {
// ---------------^^^^^
    try {
        for (const value of arr) {
            console.log(value);
            await $.ajax({
    // -----^^^^^^
                url: "import_xml_single_post.php",
                type: "post",
                data: {
                    'import_id': value
                },
                success: function(data) {
                    $("#result").append(data);
                }
            });
        }
    } catch (e) {
        // Handle/report error doing request
    }
});

在整个函数体周围有一个try/catch 非常重要,因为否则将无法处理 ajax 调用中的错误(因为 jQuery 中的任何内容都不会对 promise 做任何事情async 函数返回)。

【讨论】:

  • 谢谢,这就像一个魅力!应该考虑嵌套这样的函数.. 只是为了记录,在我的原始代码的每个请求之后添加一些时间以允许 UI 更新,这行得通吗?
  • @DavidVerbeeck - 如果您在普通函数中的 for 循环中仍然有同步请求,则不会。没有办法暂停它并让浏览器更新它的 UI。但是如果你想编写看起来同步但仍然异步运行的代码,你可以使用async 函数;我在答案中添加了一个示例和详细信息。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-11-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-05-18
  • 1970-01-01
相关资源
最近更新 更多