在for循环内, 提交同步ajax, 并将返回的值实时渲染在页面上,怎么做~~

页面有个弹窗, 会批量做一些操作..

用for循环,将列表循环出来,依次提交到接口去并将返回的值渲染到页面上.

条件:

  1. for循环
  2. ajax必须是同步的
  3. 实时渲染页面,类似进度

    for (var i = 0; i < sn.length; i++) {
        $.ajax({
            type: 'post',
            url: 'aaa.action',
            data: {'details.sn': sn[i], ...details},
            async: false,
            success: function (res) {
                if (res.normal === 1) {
                    reMsg += `<li>${res.details.sn}: <span style="color: green">${res.msg}</span></li>`
                    $('.showSn').html(reMsg)
                } else if (res.normal === 0) {
                    reMsg += `<li>${res.details.sn}: <span style="color: red">${res.msg}</span></li>`
                    $('.showSn').html(reMsg)
                }
            }
        })
    }

现在的情况是dom实时更新了,但是弹窗并没有实时渲染..,会在所有的接口执行完毕后才会渲染:

如下图

clipboard.png

clipboard.png

如果要用generater函数的话怎么写呢~?
或者,不用generater函数怎么写呢?

阅读 4.7k
3 个回答

可以用Promise啊

let innerFun = ()=>{
  return new Promise((resolve, reject)=>{
    // setTimeout可以替换成你的ajax就好了,success调用resolve
    setTimeout(()=>{
      resolve()
    }, 1000)
  })
}

let forFun = async ()=>{
  for (let i = 0; i < 15; i++) {
    await innerFun()
    console.log(i)
  }
}

forFun()

我弄实时进度的时候遇到了类似的问题
最终发现递归调用就可以了,for循环的话会ajax异步请求会锁死前端(即最终结果一次性显示),
如果你一定要用ajax同步的话配合setInterval是可以实现,但是效果不好(前端的部分动画效果可能不会动,而且请求速度也相对较慢,执行时界面卡)。
最好是用递归循环ajax异步请求,可以在单个请求seccess的时候渲染前端(不会出现ajax锁死前端的情况)。

例如:

            ajax_post(data);

            function ajax_post(data) {
                if (xxx) {//递归结束条件
                    return;
                }
                $.ajax({
                    url: '/xxx',
                    type: "post",
                    data: {
                        'data': data
                    },
                    // async:false,
                    success: function (data) {
                        change_table(data);//前端变化
                        ajax_post(data);//调自己
                    }
                });
            }

描述清楚点,这句话没懂

dom实时更新了,但是弹窗并没有实时渲染.
推荐问题