2013-03-20 97 views
1

凌乱的顺序我有一个功能,看起来像这样:操作问题

function showCreditCard(idx, data) { 

    if(typeof cardInfo == 'undefined' && parseInt($("#cc-dropdown-" + idx + " option:selected").val(),10) > -1) { 
     // actual selection made, but not default, so cardInfo hasn't been set. Need to run ajax call to get credit card; 
     console.log("show dropdown"); 
     console.log("there are saved cards and a selection was made"); 
     poGetPaymentOption('credit card', parseInt($("#cc-dropdown-" + idx + " option:selected").val(),10), idx); 

     // this is the default card; display dropdown with default selected and static fields 
     console.log("supposedly after poGetPayment"); 
     console.dir(cardInfo); 

     // why is this stuff running before poGetPaymentOtion finishes and returns a cardInfo object? 
     if(cardInfo.cc.cc_type == 'VI') { $('#cc_visaBig-'+idx).attr('class', 'cc_visaBig'); } 

     $('#cc-static-wrap-'+idx).show(); 
     updateButtonState(); 

    } 

} 

正如你可以通过评论看到,poGetPaymentOption调用后线运行之前的功能实际上是完整的。我已经通过poGetPaymentOption函数中的日志验证了这一点(下文)。

function poGetPaymentOption(type, key, bIdx) { 
    if(type == 'credit card') { 
     console.log("signed in, credit card"); 
     $.post('/site/ajax/customers/getSingleCreditCard', 
      { 'key': key }, 
      function(data) { 
      if(data.success == 1) { 
       console.log("poPayment success"); 
        if(typeof cardInfo == 'undefined') { 
         cardInfo = new saveCardInfo(data); 
        }  

      } else { 
       console.log("poPayment no success"); 
      } 
      }, 'json'); 
    } 
} 

我会希望发生的是呼叫从showCreditCardpoGetPaymentOption通过AJAX调用返回成功(其它),然后创建一个名为cardInfosaveCardInfo对象。据我所知,它确实发生,但是检查cardInfo.cc.cc_type及更高版本的行都是在创建对象之前发生的。我附上了我的Firebug控制台的屏幕截图,因此很明显,订单事情正在发生。

enter image description here

我在做什么错?我需要确保poGetPaymentOption已完全完成,并且在继续执行showCreditCard函数之前已创建了cardInfo

+1

使用$就不是$。发布并将async设置为false。 – Cristy 2013-03-20 22:52:45

+0

当poGetPaymentOption()结束时,您需要执行第一个方法的其余部分。你需要一个回调函数。 – 2013-03-20 22:54:06

+3

@Cristy:不,尽管可能,但这不可取。 – Bergi 2013-03-20 22:54:15

回答

1

AJAX调用是异步的,所以成功回调函数将在响应到达时调用,而不是立即调用。

实际上,当您的代码运行时,响应到达时发生的事件无法处理。即使响应在您退出showCreditCard函数之前到达,在您退出函数之前该事件也不会被处理,因此直到您退出showCreditCard函数后才会调用该回调函数。

为了利用获取的数据,您需要在成功回调函数中执行该操作。将代码移入该函数,或将回调函数发送到poGetPaymentOption,以便在响应到达时进行调用。

(出于完整性;进行同步调用,而不是将让你的代码工作没有清理它,但因为它冻结浏览器,同时它的等待响应这是不可取的。)

+0

我不确定我明白我应该移入成功回调的代码。 'showCreditCard'中的所有代码?这是行不通的。我在这里展示的是该函数的精简版本;它实际上在多个地方被调用,并且里面有各种各样的条件 - 并不是所有的条件都依赖于'poGetPayment',所以我不能将所有的代码移入它,而不需要在其他地方复制它,所以它可以在其他情况下被调用。 – EmmyS 2013-03-21 01:37:29

+0

@EmmyS:您只需移动依赖AJAX调用结果的代码即可。你可以在'showCreditCard'中将这段代码放在一个回调函数中,它可以让代码保持在同一个地方,但是从程序流的角度来看,代码是在一个单独的函数中。 – Guffa 2013-03-21 08:38:10

0

发生这种情况是因为$.post()异步执行。

基本上,你的JS代码在AJAX调用进入服务器的同时继续同步。只有服务器响应您的回调函数才会执行。

在您的具体例子,poGetPaymentOption('credit card', parseInt($("#cc-dropdown-" + idx + " option:selected").val(),10), idx);后,一切都将你的匿名函数被执行之前执行的方式:

 function(data) { 
     if(data.success == 1) { 
      console.log("poPayment success"); 
       if(typeof cardInfo == 'undefined') { 
        cardInfo = new saveCardInfo(data); 
       }  

     } else { 
      console.log("poPayment no success"); 
     } 
     } 

为了解决这个问题,你就需要在回调中移动你休息showCreditCard功能。或者,也可以创建另一个在回调中被调用的函数。