ajax全部执行结束再执行下一部分操作

现在页面有三个table。需要通过ajax,给每个tr加上内容。原先是ajax全部异步执行,然后出结果。现在需要先等第一个table的内容全部出来再去执行第二个的,第二个的结束了再去执行第三个的。这样的应该怎么写?我原先的写法如下:

$('.table_one_tr').each(function(i,n) {
    $.ajax({
        type : "GET",
        url : link,
        dataType : "json",
        success:function(data) {
           
        },
        error:function (data){
            
        }
    });
});

$('.table_two_tr').each(function(i,n) {
    $.ajax({
        type : "GET",
        url : link,
        dataType : "json",
        success:function(data) {
           
        },
        error:function (data){
            
        }
    });
});
$('.table_three_tr').each(function(i,n) {
    $.ajax({
        type : "GET",
        url : link,
        dataType : "json",
        success:function(data) {
           
        },
        error:function (data){
            
        }
    });
});
阅读 3.8k
5 个回答

要按顺序执行异步,比较简单的写法是使用 await。关于 await ,可以参阅:理解 JavaScript 的 async/await

jQuery.ajax 的结果虽然不是 Promise,但是 Promise Like,同样可以对其使用 await 来异步等待。只不过不能通过 .catch() 来处理错误,用 .fail() 来处理错误也不能避免抛出异常,所以必须用 try ... catch 来自处理错误。

$('.table_one_tr').each(fn),这是每有一个 .table_one_tr 就会执行一次 fn,理论上应该是很多个啊。虽然为了完成一个业务 要做这么多次 Ajax 不太合理。但如果确实需要,这里如果要一个个执行的话,就不能用 .each(),要转成 Array 直接用 for ... of

// await 必须要在 async 函数中运行,这里用一个 async 的 IIFE 封装一下
(async () => {
    for (let el in $('.table_one_tr').toArray()) {
        try {
            const data = await $.ajax(...)
            // 处理拿到的 data(就是 done/success 回调的参数)
        } catch (err) {
            // 处理错误,就是 fail/error 回调的参数
        }
    }
})();

如果这里需要并发,用 .each() 是可以,但是不知道什么时候所有并发完成,所以还是需要收集成一个 promise list,再用 Promise.all() 或者 Promise.allSettled() 来运行:

(async () => {
    const allPromise = $('.table_one_tr')
        .toArray()
        .map(() => {
            try {
                const data = await $.ajax(...)
                // 处理拿到的 data(就是 done/success 回调的参数)
            } catch (err) {
                // 处理错误,就是 fail/error 回调的参数
            }
        });
    await Promise.allSettled(allPromise);
})();

一个处理了,等待结束之后再处理另一个就容易了

(async () => {
    const allPromise1 = $('.table_one_tr').toArray().map(...);
    await Promise.allSettled(allPromise1);

    const allPromise2 = $('.table_two_tr').toArray().map(...);
    await Promise.allSettled(allPromise2);

    const allPromise3 = $('.table_three_tr').toArray().map(...);
    await Promise.allSettled(allPromise3);
})();
$('.table_one_tr').each(function(i,n) {
    $.ajax({
        type : "GET",
        url : link,
        dataType : "json",
        success:function(data) {
           
        },
        error:function (data){
            
        }
    });
});

看上去只有 $('.table_one_tr') 不同。那么我们可以封装一下 function

function tableAjax({tableQuerySelector}){
  $(tableQuerySelector).each(function(i,n) {
      $.ajax({
          type : "GET",
          url : link,
          dataType : "json",
          success:function(data) {

          },
          error:function (data){

          }
      });
  });
}
// 这里也可以改成数组循环。
await tableAjax('.table_one_tr')
await tableAjax('.table_two_tr')
await tableAjax('.table_three_tr')

// const list = ['.table_one_tr', '.table_two_tr', '.table_three_tr']
// for(const i = 0; i < list.length; i++){
//        await tableAjax({tableQuerySelector: list[i]})
// }

当然你里面还有可变的,可以把 list 改成对象,直接传入。

你可以看到我上面加了 await,但是我们的 function 目前还不是 async 。那么我们改造一下

function tableAjax({tableQuerySelector}){
    const promiseList = [];
  $(tableQuerySelector).each(function(i,n) {
        promiseList.push(
            new Promise(funciton(resolve, reject){
              $.ajax({
                  type : "GET",
                  url : link,
                  dataType : "json",
                  success:function(data) {
                        // 如果用不到 data 可以不传
                        resolve(data)
                  },
                  error:function (data){
                        // 如果用不到 data 可以不传
                        reject(data)
                  }
              });
            })
        )
  });
// 这里我们等一下所有的 Promise。当然,你还可以处理 then 或者 catch
return Promise.all(promiseList)
}

当然,你可以纯用 promise ,也可以纯用 await、async。
甚至你也可以用 jquery 自带的。

把你的ajax转成promise,
然后再包在promise.all里面

new Promise(resolve => {
  $.ajax({
    success(result) { resolve({ result }) },
    error(error) { resolve({ error }) },
  })
})
function ajax() {
    if (arguments.length) {
        var arg = Array.prototype.shift.call(arguments);
        var doms = $(arg.selector), link = arg.link;
        var length = doms.length, count = 0;
        var that = this, args = arguments;
        doms.each(function() {
            $.ajax({
                type: "GET",
                url: link,
                dataType: "json",
                success: function(data) {
                    // do something...
                    if (++count === length) {
                        ajax.apply(that, args);
                    }
                },
                error: function(data) {}
            });
        });
    }
}
ajax({
    selector: ".table_one_tr",
    link: "..."
},
{
    selector: ".table_two_tr",
    link: "..."
},
{
    selector: ".table_three_tr",
    link: "..."
});
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题