无法按顺序触发两个 jQuery ajax 调用
Cannot get two jQuery ajax calls to fire in order
我正在使用一个 JS API,我使用 POSTs 和 GET 访问它。这是针对电商平台(Shopify)的,但我不认为这个问题与平台有关。
我已经能够编写两个 POST 请求,无论是在代码中还是在控制台中,它们都完全按照需要单独执行。但是,我根本无法让他们一个接一个地开火(在我的情况下,第一个必须在第二个开始之前完成)。
第一个请求如下(清空购物车,不需要发送数据,只需要POSTed到URL):
function clearCart(){
$.ajax({
url: '/cart/clear.js',
method: 'POST',
success: function(){
console.log("cleared");
},
error: function(jqXHR, textStatus, errorThrown) {
console.log('jqXHR:');
console.log(jqXHR);
console.log('textStatus:');
console.log(textStatus);
console.log('errorThrown:');
console.log(errorThrown);
}
});
}
第二个请求如下(这会将某件商品和一定数量的所述商品添加到购物车,然后重定向到结账):
function cartAdd(quantity, id){
$.ajax({
url: '/cart/add.js',
method: 'POST',
data: {
quantity: quantity,
id: id
},
success: function(data){
console.log("added");
window.location.href = '/checkout';
},
error: function(jqXHR, textStatus, errorThrown) {
console.log('jqXHR:');
console.log(jqXHR);
console.log('textStatus:');
console.log(textStatus);
console.log('errorThrown:');
console.log(errorThrown);
}
});
}
我将它们链接在一起的方式如下所示(变量已正确填充):
$.when(
clearCart(),
cartAdd(variantQuantity, variantID)
);
经过多次测试,我有时似乎让代码正常工作(可能是 1/10 的时间)所以我被引导相信这是一个时间问题,虽然我不能肯定地说,因为我无法始终如一地测试这些结果。
我唯一真正的线索是,当我使用 .done() 时,这些函数单独工作,但是当我使用 .success() 时,它们 return 以下内容:
SyntaxError: Unexpected token :
at eval (<anonymous>)
at jquery-1.10.2.min.js?1013630…:4
at Function.globalEval (jquery-1.10.2.min.js?1013630…:4)
at text script (jquery-1.10.2.min.js?1013630…:6)
at On (jquery-1.10.2.min.js?1013630…:6)
at k (jquery-1.10.2.min.js?1013630…:6)
at XMLHttpRequest.r (jquery-1.10.2.min.js?1013630…:6)
有什么帮助吗?
更新
我实际上能够通过显式指定 'json' 的数据类型来解决语法错误。不管怎样,这两个函数仍然表现不稳定,有时只是按正确的顺序工作。
如果您的评估是正确的,您可以简单地使函数 运行 同步,以确保仅当第一个函数执行时才调用第二个函数。方法如下:
function clearCart(){
$.ajax({
url: '/cart/clear.js',
method: 'POST',
async: false,
success: function(){
console.log("cleared");
},
error: function(jqXHR, textStatus, errorThrown) {
console.log('jqXHR:');
console.log(jqXHR);
console.log('textStatus:');
console.log(textStatus);
console.log('errorThrown:');
console.log(errorThrown);
}
});
}
注意 async
属性 告诉浏览器在调用下一个函数之前等待请求完成。你不需要在第二个函数上设置它,因为你不希望在那之后执行任何东西。
此外,我建议您在第一个函数中使用回调而不是 async=false
,因为异步会损害用户体验。
clearCart()
或 cartAdd()
函数未返回任何值或 jQuery 承诺,请参阅 。 return
$.ajax()
调用,链 .then()
调用第二个函数。
function clearCart() {
return $.ajax({
url: '/cart/clear.js',
method: 'POST'
});
}
function cartAdd(quantity, id) {
return $.ajax({
url: '/cart/add.js',
method: 'POST',
data: {
quantity: quantity,
id: id
}
})
}
function handleError(jqXHR, textStatus, errorThrown) {
console.log('jqXHR:');
console.log(jqXHR);
console.log('textStatus:');
console.log(textStatus);
console.log('errorThrown:');
console.log(errorThrown);
}
clearCart()
.then(function() {
console.log("cleared")
return cartAdd(variantQuantity, variantID)
})
.then(function() {
console.log("added");
window.location.href = '/checkout';
})
.fail(handleError);
放置 async
选项的问题是这个选项使一切都挂起,直到响应。
对于这些情况:首先我们在页面的 ready
函数上调用 ajax 并将它们放在不同的 sessionStorage
中,然后在我们的函数中(这将在 ready
或者至少函数不在 ready
中,只需在 ready
中调用它)我们检查值。如果它们为空,我们会在特定时间(例如 3 秒)后使用 setTimeout
再次调用该函数,并在一段时间后设置值,我们可以在我们的函数中使用它们
示例代码:
$(document).ready(function(){
sessionStorage.setItem("firstApi",JSON.stringify(callFirstAjax()));
sessionStorage.setItem("secondApi",JSON.stringify(callSecondAjax()));
doSomething();
});
function doSomething() {
var firstApi = sessionStorage.get("firstApi");
var secondApi = sessionStorage.get("secondApi");
if(firstApi == null || secondApi == null) {
setTimeout(function() {
firstApi = null;
secondApi = null;
doSomething();
}, 3000);
}
// rest of function based on two variable values
}
顺便说一下,每个浏览器的 sessionStorage 是不同的,如果当前 window 关闭你不能,你必须重新设置它。如果您想使用类似的东西但可以从所有浏览器访问 window(您的网站在其中打开)使用 localStorage
而不是 sessionStorage
Return 保证像链接一样使用它。
function clearCart() {
return $.ajax({
url: '/cart/clear.js',
method: 'POST',
success: function() {
console.log("cleared");
},
error: function(jqXHR, textStatus, errorThrown) {
// error handler
}
});
}
function cartAdd(quantity, id){
return $.ajax({
url: '/cart/add.js',
method: 'POST',
data: {
quantity: quantity,
id: id
},
success: function(data){
console.log("added");
window.location.href = '/checkout';
},
error: function(jqXHR, textStatus, errorThrown) {
// error handler
}
});
}
现在像这样调用函数
clearCart().done( function(){
// after cart is empty, code goes below
// Example code to add item to cart
cartAdd( 3, 1);
}).fail(function(){
// clear cart failed
// put handler here if required
})
还有其他方法可以代替已弃用的方法 "async: false"。因为有时它可能会导致糟糕的结果。但是,您可以使用它。
但我会建议您使用其他方法来完成此任务:
第一:使用deferred.then()方法
例如,如果您有两个 ajax 调用:
function clearCart(){
$.ajax({
url: '/cart/clear.js',
method: 'POST',
.... });
}
function cartAdd(quantity, id){
$.ajax({
url: '/cart/add.js',
method: 'POST',
data: {
quantity: quantity,
id: id
},
.....});
}
然后只需使用 then 方法和 return 第二个 ajax 调用 promise :
$.when(clearCart(....)).then(function(){ return cartAdd(....)});
它将产生您所期望的结果或 ajax 个调用的链接。
另一种方法是将 ajax 调用放在 ajax 的成功块中。
function clearCart(){
$.ajax({
url: '/cart/clear.js',
method: 'POST',
success: function(data){
cartAdd(....);
}
...... });
}
这两种方法都会产生您所期望的结果,而且它们的好处是它们不是不推荐使用的方法。
我正在使用一个 JS API,我使用 POSTs 和 GET 访问它。这是针对电商平台(Shopify)的,但我不认为这个问题与平台有关。
我已经能够编写两个 POST 请求,无论是在代码中还是在控制台中,它们都完全按照需要单独执行。但是,我根本无法让他们一个接一个地开火(在我的情况下,第一个必须在第二个开始之前完成)。
第一个请求如下(清空购物车,不需要发送数据,只需要POSTed到URL):
function clearCart(){
$.ajax({
url: '/cart/clear.js',
method: 'POST',
success: function(){
console.log("cleared");
},
error: function(jqXHR, textStatus, errorThrown) {
console.log('jqXHR:');
console.log(jqXHR);
console.log('textStatus:');
console.log(textStatus);
console.log('errorThrown:');
console.log(errorThrown);
}
});
}
第二个请求如下(这会将某件商品和一定数量的所述商品添加到购物车,然后重定向到结账):
function cartAdd(quantity, id){
$.ajax({
url: '/cart/add.js',
method: 'POST',
data: {
quantity: quantity,
id: id
},
success: function(data){
console.log("added");
window.location.href = '/checkout';
},
error: function(jqXHR, textStatus, errorThrown) {
console.log('jqXHR:');
console.log(jqXHR);
console.log('textStatus:');
console.log(textStatus);
console.log('errorThrown:');
console.log(errorThrown);
}
});
}
我将它们链接在一起的方式如下所示(变量已正确填充):
$.when(
clearCart(),
cartAdd(variantQuantity, variantID)
);
经过多次测试,我有时似乎让代码正常工作(可能是 1/10 的时间)所以我被引导相信这是一个时间问题,虽然我不能肯定地说,因为我无法始终如一地测试这些结果。
我唯一真正的线索是,当我使用 .done() 时,这些函数单独工作,但是当我使用 .success() 时,它们 return 以下内容:
SyntaxError: Unexpected token :
at eval (<anonymous>)
at jquery-1.10.2.min.js?1013630…:4
at Function.globalEval (jquery-1.10.2.min.js?1013630…:4)
at text script (jquery-1.10.2.min.js?1013630…:6)
at On (jquery-1.10.2.min.js?1013630…:6)
at k (jquery-1.10.2.min.js?1013630…:6)
at XMLHttpRequest.r (jquery-1.10.2.min.js?1013630…:6)
有什么帮助吗?
更新 我实际上能够通过显式指定 'json' 的数据类型来解决语法错误。不管怎样,这两个函数仍然表现不稳定,有时只是按正确的顺序工作。
如果您的评估是正确的,您可以简单地使函数 运行 同步,以确保仅当第一个函数执行时才调用第二个函数。方法如下:
function clearCart(){
$.ajax({
url: '/cart/clear.js',
method: 'POST',
async: false,
success: function(){
console.log("cleared");
},
error: function(jqXHR, textStatus, errorThrown) {
console.log('jqXHR:');
console.log(jqXHR);
console.log('textStatus:');
console.log(textStatus);
console.log('errorThrown:');
console.log(errorThrown);
}
});
}
注意 async
属性 告诉浏览器在调用下一个函数之前等待请求完成。你不需要在第二个函数上设置它,因为你不希望在那之后执行任何东西。
此外,我建议您在第一个函数中使用回调而不是 async=false
,因为异步会损害用户体验。
clearCart()
或 cartAdd()
函数未返回任何值或 jQuery 承诺,请参阅 return
$.ajax()
调用,链 .then()
调用第二个函数。
function clearCart() {
return $.ajax({
url: '/cart/clear.js',
method: 'POST'
});
}
function cartAdd(quantity, id) {
return $.ajax({
url: '/cart/add.js',
method: 'POST',
data: {
quantity: quantity,
id: id
}
})
}
function handleError(jqXHR, textStatus, errorThrown) {
console.log('jqXHR:');
console.log(jqXHR);
console.log('textStatus:');
console.log(textStatus);
console.log('errorThrown:');
console.log(errorThrown);
}
clearCart()
.then(function() {
console.log("cleared")
return cartAdd(variantQuantity, variantID)
})
.then(function() {
console.log("added");
window.location.href = '/checkout';
})
.fail(handleError);
放置 async
选项的问题是这个选项使一切都挂起,直到响应。
对于这些情况:首先我们在页面的 ready
函数上调用 ajax 并将它们放在不同的 sessionStorage
中,然后在我们的函数中(这将在 ready
或者至少函数不在 ready
中,只需在 ready
中调用它)我们检查值。如果它们为空,我们会在特定时间(例如 3 秒)后使用 setTimeout
再次调用该函数,并在一段时间后设置值,我们可以在我们的函数中使用它们
示例代码:
$(document).ready(function(){
sessionStorage.setItem("firstApi",JSON.stringify(callFirstAjax()));
sessionStorage.setItem("secondApi",JSON.stringify(callSecondAjax()));
doSomething();
});
function doSomething() {
var firstApi = sessionStorage.get("firstApi");
var secondApi = sessionStorage.get("secondApi");
if(firstApi == null || secondApi == null) {
setTimeout(function() {
firstApi = null;
secondApi = null;
doSomething();
}, 3000);
}
// rest of function based on two variable values
}
顺便说一下,每个浏览器的 sessionStorage 是不同的,如果当前 window 关闭你不能,你必须重新设置它。如果您想使用类似的东西但可以从所有浏览器访问 window(您的网站在其中打开)使用 localStorage
而不是 sessionStorage
Return 保证像链接一样使用它。
function clearCart() {
return $.ajax({
url: '/cart/clear.js',
method: 'POST',
success: function() {
console.log("cleared");
},
error: function(jqXHR, textStatus, errorThrown) {
// error handler
}
});
}
function cartAdd(quantity, id){
return $.ajax({
url: '/cart/add.js',
method: 'POST',
data: {
quantity: quantity,
id: id
},
success: function(data){
console.log("added");
window.location.href = '/checkout';
},
error: function(jqXHR, textStatus, errorThrown) {
// error handler
}
});
}
现在像这样调用函数
clearCart().done( function(){
// after cart is empty, code goes below
// Example code to add item to cart
cartAdd( 3, 1);
}).fail(function(){
// clear cart failed
// put handler here if required
})
还有其他方法可以代替已弃用的方法 "async: false"。因为有时它可能会导致糟糕的结果。但是,您可以使用它。 但我会建议您使用其他方法来完成此任务:
第一:使用deferred.then()方法 例如,如果您有两个 ajax 调用:
function clearCart(){
$.ajax({
url: '/cart/clear.js',
method: 'POST',
.... });
}
function cartAdd(quantity, id){
$.ajax({
url: '/cart/add.js',
method: 'POST',
data: {
quantity: quantity,
id: id
},
.....});
}
然后只需使用 then 方法和 return 第二个 ajax 调用 promise :
$.when(clearCart(....)).then(function(){ return cartAdd(....)});
它将产生您所期望的结果或 ajax 个调用的链接。
另一种方法是将 ajax 调用放在 ajax 的成功块中。
function clearCart(){
$.ajax({
url: '/cart/clear.js',
method: 'POST',
success: function(data){
cartAdd(....);
}
...... });
}
这两种方法都会产生您所期望的结果,而且它们的好处是它们不是不推荐使用的方法。