What I'm Trying To Accomplish
I need to trigger 1 to 3 different $.post()
requests, and whether it's 1 call, 2 consecutive calls, or 3 consecutive calls is decided by some basic user selection. Each call must only start after the previous is completely finished.
我需要触发1到3个不同的$ .post()请求,以及它是1个呼叫,2个连续呼叫还是3个连续呼叫是由一些基本用户选择决定的。每次调用必须仅在上一次完成后才开始。
I am dealing with 3 simple behavior cases -- the user, being presented with "Checkbox 1," "Checkbox 2," and a "Continue" button," opts to
我正在处理3个简单的行为案例 - 用户,出现“Checkbox 1”,“Checkbox 2”和“Continue”按钮,“选择
- Select nothing and then press "Continue" button, which makes an XHR call to '/remote.php',
- The user opts to only select "Checkbox 1" or "Checkbox 2," and then presses "Continue" button, which calls
$.post() Function 1
that is bound to Checkbox 1, or$.post() Function 2
that is bound to Checkbox 2, and then makes an XHR call to '/remote.php', - Or the user selects both Checkbox 1 + 2 and then presses Continue, which calls
$.post() Function 1
, then calls$.post() Function 2
, and then makes an XHR call to '/remote.php'.
选择任何内容然后按“继续”按钮,这会对XRR调用'/remote.php',
用户选择仅选择“Checkbox 1”或“Checkbox 2”,然后按“Continue”按钮,该按钮调用$ .post()函数1绑定到Checkbox 1,或$ .post()函数2,即绑定到Checkbox 2,然后对'/remote.php'进行XHR调用,
或者用户选择Checkbox 1 + 2然后按Continue,调用$ .post()函数1,然后调用$ .post()函数2,然后对'/remote.php'进行XHR调用。
I need to make sure that the Continue-button $.post()
function does not fire until the Checkbox-bound $.post()
functions fire and complete.
我需要确保在Checkbox绑定的$ .post()函数触发并完成之前,不会触发Continue-button $ .post()函数。
The Problem
The problem is that if Checkbox 1 is selected and Checkbox 2 is selected, and then the Continue button is pressed, as I understand it, the loading order should be:
问题是,如果选中Checkbox 1并选中Checkbox 2,然后按下Continue按钮,据我所知,加载顺序应为:
- Checkbox 1 bound
$.post()
request fires and completes, then - Checkbox 2 bound
$.post()
request fires and completes, then - Continue button bound
$.post()
fires, and pages is changed via AJAX at the end of the function tied to "Continue" button bound function.
复选框1绑定$ .post()请求触发并完成,然后
复选框2绑定$ .post()请求触发并完成,然后
触发按钮绑定$ .post()触发,并在与“继续”按钮绑定功能绑定的功能结束时通过AJAX更改页面。
So, where the result should look like:
那么,结果应该是这样的:
XHR finished loading: POST "/cart.php?action=add&product_id=1280".
XHR finished loading: POST "/cart.php?action=add&product_id=1284".
XHR finished loading: POST "/remote.php".
It instead often comes out like this:
它经常出现如下:
XHR finished loading: POST "/cart.php?action=add&product_id=1280".
XHR finished loading: POST "/remote.php".
XHR finished loading: POST "/cart.php?action=add&product_id=1284".
So when the page changes due to the AJAX at the end of the "last"/"Continue-button function, either neither of the Checkbox 1 or Checkbox 2 actions have taken place, or one of the two or both do register in the backend (ie, added to cart) but do not reflect in the AJAXified DOM as they should as the final AJAX fires and completes before the previous $.post() calls have completed.
因此,当页面由于“最后”/“继续按钮功能结束时的AJAX而发生变化时,Checkbox 1或Checkbox 2操作都没有发生,或者两者之一或两者都在后端注册(即添加到购物车中)但不反映在AJAXified DOM中,因为最终的AJAX会在之前的$ .post()调用完成之前触发并完成。
My Code
The HTML
The HTML is basic:
HTML是基本的:
<form method="post" action="#" onsubmit="newChooseShippingProvider(); return false;">
<label for="delSigCheck" class="del-sig-text"><input id="delSigCheck" type="checkbox" onchange="addDelSigToCart();" title="Add Delivery Signature"></label>
<label for="addInsCheck" class="ins-add-calc"><input id="addInsCheck" type="checkbox" onchange="addInsToCart();" title="Add Delivery Signature" data-ins-id="1284"></label>
<input type="submit" value="Continue" class="btn Small">
</form>
The Javascript/jQuery
This is my latest--4th or 5th--attempt, and still does not work:
这是我最近的 - 第4次或第5次尝试,但仍然不起作用:
function addDelSigToCart() {
$('#delSigCheck').toggleClass('checked');
}
function addInsToCart() {
$('#addInsCheck').toggleClass('checked');
}
function newChooseShippingProvider() {
var originalCheckout = ExpressCheckout.ChooseShippingProvider();
if ($('.ShippingProviderList .radio span').hasClass('checked')) {
var addInsCheck = $('#addInsCheck').hasClass('checked');
var delSigCheck = $('#delSigCheck').hasClass('checked');
var insId = $('#addInsCheck').attr('data-ins-id');
var addDelSigUrl = '/cart.php?action=add&product_id=1280';
var addInsUrl = '/cart.php?action=add&product_id=' + insId;
if (delSigCheck && addInsCheck) {
$.post(addDelSigUrl, function() {
$.post(addInsUrl, function() {
originalCheckout;
});
});
} else if (!delSigCheck && !addInsCheck) {
originalCheckout;
} else if (delSigCheck && !addInsCheck) {
$.post(addDelSigUrl, function() {
originalCheckout;
});
} else if (!delSigCheck && addInsCheck) {
$.post(addInsUrl, function() {
originalCheckout;
});
}
} else {
originalCheckout;
}
What I've Tried
I've gone through several version of chaining the $.post()
calls, but nothing seems to work consistently.
我已经经历了几个链接$ .post()调用的版本,但似乎没有任何工作。
What I am using now and what seems to work the best for me with extensive testing is using setTimeout
to chain the function with some delay, like this:
我现在使用的是什么似乎对我来说最好的广泛测试是使用setTimeout链接函数有一些延迟,像这样:
...
if (delSigCheck && addInsCheck) {
$.post(addDelSigUrl);
setTimeout(function() {
$.post(addInsUrl);
setTimeout(function() {
ExpressCheckout.ChooseShippingProvider();
}, 1300);
}, 1300);
} else if ...
And this version above is what I'm using now, as it seems to give the most consistent results, seeing the scripts load typically as 1,2,3, followed by a DOM AJAXified with appropriate changes based on function 1 and 2. However, I don't think the setTimeout is working as even when I increase it to 5000 or 10000, the action is performed "instantaneously" and no delay takes place (at least certainly nothing close to 5-10 seconds).
上面这个版本就是我现在使用的,因为它似乎给出了最一致的结果,看到脚本通常加载为1,2,3,然后是基于函数1和2的适当更改的DOM AJAXified。 ,我不认为setTimeout工作正常,即使我将其增加到5000或10000,动作“瞬间”执行并且没有发生延迟(至少肯定没有接近5-10秒)。
I've also tried putting the functions inside $.post()
's success callback:
我也尝试将函数放在$ .post()的成功回调中:
...
if (delSigCheck && addInsCheck) {
$.post(addDelSigUrl, function() {
setTimeout(function() {
$.post(addInsUrl, function() {
setTimeout(function() {
originalCheckout;
}, 1300);
});
}, 1300);
});
} else if ...
And finally I've also tried:
最后我也尝试过:
$.when($.post(addDelSigUrl)).then(originalCheckout);
as well as .done
and success:
but none of it works, and the $.posts()'s load in an unexpected order, failing.
以及.done和success:但它们都不起作用,并且$ .posts()以意想不到的顺序加载,失败了。
The Question
- What am I doing wrong?
- How can I make it so 1 loads fully, then 2 loads fully, and only then 3 fires and loads?
我究竟做错了什么?
我怎样才能使它完全加载,然后完全加载2次,然后只有3次加载和加载?
UPDATE 1:
I just tried jfriend00's answer:
我刚试过jfriend00的回答:
$.post(addDelSigUrl, { cache: false }).then(function(data1) {
//CONSOLE.LOGing HERE
console.log(data1);
return $.post(addInsUrl, { cache: false });
}).then(function(data2) {
//CONSOLE.LOGing HERE
console.log(data2);
return originalCheckout;
});
But it still resulted in:
但它仍然导致:
XHR finished loading: POST "/cart.php?action=add&product_id=1280".
XHR finished loading: POST "/remote.php".
XHR finished loading: POST "/cart.php?action=add&product_id=1284".
and both console.logs fire immediately after the first "XHR ...", THEN /remote.php fires (though it should fire last as part of originalCheckout), THEN the 3rd XHR fires.
并且两个console.logs在第一个“XHR ...”之后立即触发,然后THEN /remote.php触发(尽管它应该作为originalCheckout的一部分触发),然后第3个XHR触发。
UPDATE 2
Now that we got the XHRs firing and loading in the correct order via .then()
, the second part of the problem I am having is that the 3rd XHR to /remote.php
updates the DOM via AJAX with data from the backend. Part of that data is the 1st and 2nd $.posts
.
现在我们已经通过.then()以正确的顺序触发XHR,我遇到的问题的第二部分是第三个XHR到/remote.php通过AJAX用来自后端的数据更新DOM。部分数据是第1和第2个.posts。
I think the 3rd AJAX call is firing and completing milliseconds before some action is taken on the backend via server-side PHP, and because of this more than 50% of the time, the DOM update via the 3rd AJAX call is missing the data from the 1st and/or 2nd call (most often the DOM changes include Checkbox 1/AJAX call 1, but not 2).
我认为第三个AJAX调用是在通过服务器端PHP在后端采取某些操作之前触发并完成毫秒,并且由于这个超过50%的时间,通过第三个AJAX调用的DOM更新缺少来自第一次和/或第二次调用(最常见的是DOM更改包括Checkbox 1 / AJAX调用1,但不包括2)。
How can I fix this? I've tried setTimeout but it doesn't seem to work as even when I set it to like 30000, the 3rd AJAX fires as soon as the 1st/2nd complete.
我怎样才能解决这个问题?我已经尝试了setTimeout,但它似乎不起作用,即使我将它设置为30000,第三个AJAX在第一个/第二个完成后立即激活。
Latest front-end code:
最新前端代码:
function newChooseShippingProvider() {
if ($('.ShippingProviderList .radio span').hasClass('checked')) {
var addInsCheck = $('#addInsCheck').hasClass('checked');
var delSigCheck = $('#delSigCheck').hasClass('checked');
var insId = $('#addInsCheck').attr('data-ins-id');
var addDelSigUrl = '/cart.php?action=add&product_id=1280';
var addInsUrl = '/cart.php?action=add&product_id=' + insId;
if (delSigCheck && addInsCheck) {
$.post(addDelSigUrl).then(function(data1) {
return $.post(addInsUrl);
}).then(function(data2) {
return ExpressCheckout.ChooseShippingProvider();
});
} else if (!delSigCheck && !addInsCheck) {
ExpressCheckout.ChooseShippingProvider();
} else if (delSigCheck && !addInsCheck) {
$.post(addDelSigUrl).then(function(data1) {
return ExpressCheckout.ChooseShippingProvider();
});
} else if (!delSigCheck && addInsCheck) {
$.post(addInsUrl).then(function(data1) {
return ExpressCheckout.ChooseShippingProvider();
});
}
} else {
ExpressCheckout.ChooseShippingProvider();
}
}
2 个解决方案
#1
3
The simplest way to sequence jQuery ajax operations is to use the built-in promises:
对jQuery ajax操作进行排序的最简单方法是使用内置的promise:
$.post(...).then(function(data1) {
return $.post(...);
}).then(function(data2) {
return $.post(...);
}).then(function(data3) {
// everything done here
});
Working demo that shows you the precise sequencing: http://jsfiddle.net/jfriend00/zcfr2xy0/
工作演示,向您展示精确的排序:http://jsfiddle.net/jfriend00/zcfr2xy0/
OK, it appears that the problem is that you're doing this:
好吧,看来问题是你这样做:
var originalCheckout = ExpressCheckout.ChooseShippingProvider();
And, then you think that sometime later, you can just do:
而且,你认为以后的某个时候,你可以这样做:
originalCheckout;
and that will somehow execute the former. That's not the case. Your ExpressCheckout.ChooseShippingProvider()
function is executed immediately and the return result from executing that function is assigned to originalCheckout
.
这将以某种方式执行前者。事实并非如此。您的ExpressCheckout.ChooseShippingProvider()函数立即执行,执行该函数的返回结果将分配给originalCheckout。
You simply can't do it that way. When you have ()
after a function name, that means to execute it NOW. I would suggest that you just replace all instances of originalCheckout;
with ExpressCheckout.ChooseShippingProvider();
.
你不能这样做。如果在函数名后面有(),则意味着现在执行它。我建议您只替换originalCheckout的所有实例;使用ExpressCheckout.ChooseShippingProvider();.
#2
1
If you "chain" AJAX post operations (meaning that you do your process once receiving the data from the previous call) then nothing strange should happen.
如果你“链接”AJAX后期操作(意味着你一旦接收到前一次调用的数据就完成了你的过程),那么就不会发生任何奇怪的事情。
From the symptom I'd think more to some cache-related problem. Adding an extra random value to the query is a quick'n dirty way to get rid of whoever is caching the result and responding instead of who should. Also using a POST request instead of a GET (if possible) may help on this issue and better conveys the idea that the operation is a mutation that should not be skipped or done out of order.
从症状我会想到更多与缓存相关的问题。为查询添加一个额外的随机值是一种快速的方法来摆脱任何缓存结果和响应的人而不是谁应该。同样使用POST请求而不是GET(如果可能的话)可能有助于解决这个问题,并且更好地传达了操作是一个不应该跳过或不按顺序完成的突变的想法。
Note that a stale response problem could be at several levels: browser, proxy, web server, cms plugin...
请注意,陈旧的响应问题可能分为几个层次:浏览器,代理,Web服务器,cms插件......
#1
3
The simplest way to sequence jQuery ajax operations is to use the built-in promises:
对jQuery ajax操作进行排序的最简单方法是使用内置的promise:
$.post(...).then(function(data1) {
return $.post(...);
}).then(function(data2) {
return $.post(...);
}).then(function(data3) {
// everything done here
});
Working demo that shows you the precise sequencing: http://jsfiddle.net/jfriend00/zcfr2xy0/
工作演示,向您展示精确的排序:http://jsfiddle.net/jfriend00/zcfr2xy0/
OK, it appears that the problem is that you're doing this:
好吧,看来问题是你这样做:
var originalCheckout = ExpressCheckout.ChooseShippingProvider();
And, then you think that sometime later, you can just do:
而且,你认为以后的某个时候,你可以这样做:
originalCheckout;
and that will somehow execute the former. That's not the case. Your ExpressCheckout.ChooseShippingProvider()
function is executed immediately and the return result from executing that function is assigned to originalCheckout
.
这将以某种方式执行前者。事实并非如此。您的ExpressCheckout.ChooseShippingProvider()函数立即执行,执行该函数的返回结果将分配给originalCheckout。
You simply can't do it that way. When you have ()
after a function name, that means to execute it NOW. I would suggest that you just replace all instances of originalCheckout;
with ExpressCheckout.ChooseShippingProvider();
.
你不能这样做。如果在函数名后面有(),则意味着现在执行它。我建议您只替换originalCheckout的所有实例;使用ExpressCheckout.ChooseShippingProvider();.
#2
1
If you "chain" AJAX post operations (meaning that you do your process once receiving the data from the previous call) then nothing strange should happen.
如果你“链接”AJAX后期操作(意味着你一旦接收到前一次调用的数据就完成了你的过程),那么就不会发生任何奇怪的事情。
From the symptom I'd think more to some cache-related problem. Adding an extra random value to the query is a quick'n dirty way to get rid of whoever is caching the result and responding instead of who should. Also using a POST request instead of a GET (if possible) may help on this issue and better conveys the idea that the operation is a mutation that should not be skipped or done out of order.
从症状我会想到更多与缓存相关的问题。为查询添加一个额外的随机值是一种快速的方法来摆脱任何缓存结果和响应的人而不是谁应该。同样使用POST请求而不是GET(如果可能的话)可能有助于解决这个问题,并且更好地传达了操作是一个不应该跳过或不按顺序完成的突变的想法。
Note that a stale response problem could be at several levels: browser, proxy, web server, cms plugin...
请注意,陈旧的响应问题可能分为几个层次:浏览器,代理,Web服务器,cms插件......