无法按顺序获取两个jQuery ajax调用

时间:2017-07-15 03:33:49

标签: javascript jquery ajax shopify

我正在使用通过POST和GET访问的JS API。这是一个电子通信平台(Shopify),但我不认为这个问题与平台有关。

我已经能够编写两个POST请求,无论是在代码中还是在控制台中,都可以根据需要单独执行。但是,我根本无法让它们一个接一个地开火(第一个必须在我的情况下第二个开始之前完成)。

第一个请求如下(这清除了购物车,不需要发送数据,只需要将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)
);

经过大量测试后,我有时似乎能够正常运行代码(可能是十分之一的时间),所以我认为这是一个时间问题,尽管我不能肯定地说我可以'不断测试这些结果。

我唯一真正的线索是当我使用.done()时函数单独工作,但是当我使用.success()时,它们会返回以下内容:

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'的数据类型来解决语法错误。无论如何,这两个函数仍然表现不正常,有时只能以正确的顺序工作。

5 个答案:

答案 0 :(得分:1)

如果您的评估是正确的,您可以简单地使函数同步运行,以确保仅在第一个函数执行时调用第二个函数。这是你如何做到的:

  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,因为异步往往会损害用户体验。

参考:http://api.jquery.com/jquery.ajax/

答案 1 :(得分:0)

clearCart()cartAdd()函数均未返回任何值或jQuery承诺,请参阅Why is value undefined at .then() chained to Promise?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);

答案 2 :(得分:0)

放置async选项的问题在于此选项会使所有内容都挂起,直到响应。

对于这些情况:首先我们在页面的ready函数上调用ajax并将它们放在不同的sessionStorage s中,然后放在我们的函数中(它将在ready之外或者至少该函数不在ready中,只需在ready中调用它)我们检查值。如果它们为null,我们在特定时间(例如3s)之后再次调用该函数使用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对于每个浏览器都是不同的,如果当前窗口关闭则不能,你必须再次设置它。如果您想使用类似的内容但可以访问所有浏览器窗口(您的网站在其中打开),请使用localStorage代替sessionStorage

答案 3 :(得分:0)

返回承诺,使其像链接一样使用。

  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
  })

答案 4 :(得分:0)

还有其他方法,而不是使用弃用的方法“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方法并返回第二个ajax调用作为promise:

$.when(clearCart(....)).then(function(){ return cartAdd(....)});

这将导致您对ajax Calls的期望或链接。

另一种方法是将ajax调用放在ajax的成功块中。

function clearCart(){
   $.ajax({
   url: '/cart/clear.js',
   method: 'POST',
   success: function(data){
      cartAdd(....);
   }
   ...... });
  }

这两种方法都会产生你所期望的,而它们的优点是它们不是被弃用的方法。