Javascript 嵌套jQuery AJAX请求以奇怪的顺序完成

Javascript 嵌套jQuery AJAX请求以奇怪的顺序完成,javascript,jquery,ajax,promise,Javascript,Jquery,Ajax,Promise,这是对我所经历的问题的重述,我认为这个问题来自于X,Y问题。我希望这个问题更接近我所经历的问题的核心。有关代码,请参见Github上的 问题 我有一个延迟jQuery对象数组,当打开时,我调用它。这些函数向修改数据的服务器发送POST请求。$。当调用包装在$中时。获取回调。这要求我修改数据字段,以满足授权要求。代码如下: $.get('/admin/students/contacts/scchange/phoneTlcForm.html?frn=001' + studentsdcid, func

这是对我所经历的问题的重述,我认为这个问题来自于X,Y问题。我希望这个问题更接近我所经历的问题的核心。有关代码,请参见Github上的

问题 我有一个延迟jQuery对象数组,当打开时,我调用它。这些函数向修改数据的服务器发送POST请求。
$。当
调用包装在
$中时。获取
回调。这要求我修改数据字段,以满足授权要求。代码如下:

$.get('/admin/students/contacts/scchange/phoneTlcForm.html?frn=001' + studentsdcid, function () {
  console.log('get callback reached');
  $.when.apply($j, phoneAjaxCalls).done(function () {
    console.log('phoneAjaxCalls promises resolved');
    returnToStudentContacts();
  });
});
我正在使用
phoneAjaxCalls.push(newPhone(tlcPhone,studentsdcid))
将ajax调用推送到数组,而newPhone返回一个ajax延迟对象:

function newPhone(tlcPhone, studentsdcid) {
    //Create new phone
    return function() {
        return $j.ajax({
            type: 'POST',
            url: '/admin/changesrecorded.white.html',
            data: tlcPhone
        });    
    };
}
当运行此代码时,我在控制台中看到“get callback Reach”在“phoneAjaxCalls Promissions resolved”之前打印,这表明请求是按照代码中显示的顺序发送的。然而,Chrome的DevTools网络选项卡似乎表明phoneAjaxCalls网络请求在加载
phoneTlcForm.html
文档之前完成

前6个请求都是
phoneAjaxCalls
请求,最后一个请求是
phoneTlcForm.html
,来自
$.get
,但这应该是第一个请求

后端接收这些请求的顺序似乎与网络选项卡显示的顺序相同,因为我在对这些
phoneAjaxCalls
请求的响应中收到授权错误

需要做的是,对
phoneTlcForm.html
的请求应该在发出任何
phoneAjaxCalls
请求之前完成

背景
我的项目是一个插件,所以我不能修改后端逻辑来简化这个过程。我所连接的系统在创建或更新数据时有一定的授权要求。在发送修改数据的请求之前,后端系统必须“看到”要修改的数据字段已呈现在HTML页面中。这就是为什么我需要在其他请求之前加载
phoneTlcForm.html
页面。

这里发生的事情是,当您构建
phoneAjaxCalls
数组时,您为每个单独的项调用
$j.ajax
。每个请求都将在您拨打该电话后立即发出。
我猜当你调用
$j.when.apply($j,phoneAjaxCalls)
时,那里的大部分承诺都已经解决了,完成的回调会立即调用

让我试着用一些评论来说明:

// previous ajax requests already fired!
$j.get('/admin/students/contacts/scchange/phoneTlcForm.html?frn=001' + studentsdcid, function () {
  console.log('get callback reached');
  // inspect the state of phoneAjaxCalls here
  // they might be resolved already.

  // you want to exec those ajax calls here, not before!
  $j.when.apply($j, phoneAjaxCalls).done(function () {
    console.log('phoneAjaxCalls promises resolved');
    returnToStudentContacts();
  });
});
所以从这里你有不同的方法来解决它。我想你在面试中已经得到了很好的回应

在每个返回$j.ajax的地方,都可以返回一个函数包装,以避免执行。让我们以以下内容为例:

return function(){
    return $j.ajax({
            url: '/ws/schema/table/' + config.contactsEmailTable + '/' + emailRecordId,
            data: JSON.stringify(emailUpdateData),
            dataType: 'json',
            contentType: "application/json; charset=utf-8",
            type: 'PUT'
        });
 };
包装完所有这些后,您可以这样称呼它们:

$.get('/admin/students/contacts/scchange/phoneTlcForm.html?frn=001' + studentsdcid, function () {
  var phoneAjaxCallsPromises = $.map(phoneAjaxCalls, function(c){
    return c();
  });
  $.when.apply($j, phoneAjaxCalls).done(function () {
    console.log('phoneAjaxCalls promises resolved');
    returnToStudentContacts();
  });
}); 

此解决方案感觉像是一种黑客攻击,但了解问题可能使您能够实施正确的修复。

为什么将promise对象推入
phoneAjaxCalls
数组会调用promise?我认为您可以传递承诺/延期,在使用then()或done()之前它们不会执行。这是$.ajax、$.get等的行为。请求将在您进行调用时立即触发,并返回承诺以跟踪其状态。您可以传递承诺,但done()调用与触发实际执行无关。我知道这里不赞成这样做,但非常感谢!你帮助修复了一个引起很多头痛的bug,我学到了一些东西:DThanks!非常高兴能帮上忙!