2017-02-18 90 views
0

我有一个使用ajax post方法和dataTables的程序。摆弄了几个星期后,我确定我根本不明白javascript是如何工作的。 这里是我的javascript:确保javascript函数按特定顺序执行

$('#SaveTimeSheet').click(function() { 
      $("#TimeSheetLoader").removeClass("hidden"); 
      GetSheetCount(); 
     }); 
     function GetSheetCount() { 
      $.ajax({ 
       url: '@Url.Action("GetTimeSheetCount","TimeSheet",null)', 
       type: "POST", 
       data:{ 
        OperatorId: $("#OperatorId option:selected").val() 
       }, 
       success: function (Result) { 
        StartTimeSheet(Result.Result); 
       } 
      }); 
     } 
     function StartTimeSheet(Result) { 
      $.ajax({ 
       type: "POST", 
       url: '@Url.Action("Create", "TimeSheet", null)', 
       data: { 
        SpecificLocation: $("#SpecificLocation").val(), 
        DetailedPoint: $("#DetailedPoint").val(), 
        SheetStatus: $("#statusSlider").val(), 
        Description: $("#Description").val(), 
        OperatorHours: $("#OperatorHoursSlider").attr("data-value"), 
        OperatorMins: $("#OperatorMinsSlider").attr("data-value"), 
        AssistantHours: $("#AssistantHoursSlider").attr("data-value"), 
        AssistantMins: $("#AssistantMinsSlider").attr("data-value"), 
        OriginalQuote: $('input[name=OriginalQuote]:checked').val(), 
        QuoteNo: $("#QuoteNo").val(), 
        SINumber: $("#SINumber").val(), 
        OperatorId: $("#OperatorId option:selected").val(), 
        SiteName: $("#SiteId option:selected").text(), 
        Code: $("#SiteId option:selected").val() + "-" + $("#OperatorId option:selected").val() + "-" + (Result + 1) + "-" + today 
       }, 
       success: function (Result) { 
        ProcessTable(Result.Result);      
       }, 
       error: function (x, e) { 
        if (x.status == 0) { 
         alert('You are offline!!\n Please Check Your Network.'); 
        } else if (x.status == 404) { 
         alert('Requested URL not found.'); 
        } else if (x.status == 500) { 
         alert('Internel Server Error.'); 
        } else if (e == 'parsererror') { 
         alert('Error.\nParsing JSON Request failed.'); 
        } else if (e == 'timeout') { 
         alert('Request Time out.'); 
        } else { 
         alert('Unknow Error.\n' + x.responseText); 
        } 
       } 
      }); 
     } 

     function ProcessTable(Result) { 
      console.log("Start Table Process"); 
      var datas = t.rows().data(); 
      var total = $("#Table tr").length - 1; 
      var counter = 0; 
      for (var i = 0; i < total; i++) { 
       var value = datas[i]; 
       AddItems(value, Result); 
       counter = counter + 1; 
      } 
      if (counter === total) { 
       SendPDF(Result); 
      } 
     } 

     function AddItems(value, Result) { 
       $.ajax({ 
        type: "POST", 
        url: '@Url.Action("ProcessTable","TimeSheet",null)', 
        data: { 
         TimeSheetId:Result, 
         BOM_NO: value[0], 
         Stock_Code: value[1], 
         Stock_Description: value[2], 
         Quantity: value[3] 
        }, 
        success: function (data) { 
         console.log(data.Result); 
        }, 
        error: function() { 
         console.log("Error"); 
        } 
       }); 
     } 
     function SendPDF(Result) { 
      $.ajax({ 
       type: "GET", 
       url: '/TimeSheet/SendTimeSheet?Id='+Result, 
       success: function (data) { 
        console.log(data.Result); 
        location.reload(); 
       } 
      }); 
     } 

我一直有麻烦的是,在程序执行中ProcessTable功能的中间SendPDF功能。我试图通过使用if语句来阻止它,但它仍然执行。

如果你知道如何解决我的代码,太棒了。但是,如果你能解释javascript如何执行函数,并且按照什么顺序。以及如何控制该订单。那太好了。

+2

我不认为这与JS具体有什么关系,因为afaik,JS中的函数调用与其他语言中的调用相同。这听起来更像是一个同步/异步的误解。 – Carcigenicate

+0

我不明白你遇到的问题是什么。 '我遇到的麻烦是程序正在执行ProcessTable函数中间的Send pdf函数.'。你可以从'ProcessTable'调用'SendPDF',所以我希望它可以运行。有什么问题? – Carcigenicate

+0

你的问题是调用'AddItems(value,Result);'在你的'ProcessTable'函数中,在所有'AddItems'调用之前循环都会完成。 – LGSon

回答

1

但是,如果你能解释javascript如何执行函数,并且按照什么顺序。以及如何控制该订单。那太好了。

JavaScript函数与大多数其他语言的函数一样工作:当调用一个函数时,它会运行到完成状态,然后控制返回到您调用它的位置。 (在大多数JavaScript环境中,您甚至不必担心多个线程,因为虽然JavaScript不是单线程语言,但大多数使用它的环境在每个全局环境中只使用一个线程,这使得生活变得非常活跃更简单。)

您的代码中的问题是异步性。在您的代码中,SendPDF未在ProcessResults中间调用;在所有对AddItems的调用完成并返回之后,它被称为接近结束。 ,当你调用AddItems,它是所有开始的过程(一个ajax请求),其然后继续异步,分别从运行你的JavaScript线程。所以SendPDF被称为之前所有这些ajax调用都有机会完成。

为了解决这个问题,我们等待这些Ajax调用具有完整AddItems回报的承诺,$.ajax给我们:

function AddItems(value, Result) { 
    // Return the Deferred that $.ajax gives us 
    return $.ajax({ 
     type: "POST", 
     url: '@Url.Action("ProcessTable","TimeSheet",null)', 
     data: { 
      TimeSheetId: Result, 
      BOM_NO: value[0], 
      Stock_Code: value[1], 
      Stock_Description: value[2], 
      Quantity: value[3] 
     }, 
     success: function(data) { 
      console.log(data.Result); 
     }/*, - Probably don't want this, instead we'll handle 
       errors in the calling code 
     error: function() { 
      console.log("Error"); 
     }*/ 
    }); 
} 

...然后在ProcessResults等到所有这些承诺的决心(这后来情况发生,ProcessResults返回之后):

function ProcessTable(Result) { 
    console.log("Start Table Process"); 
    var datas = t.rows().data(); 
    var total = $("#Table tr").length - 1; 
    // Remember the promises from AddItems in an array 
    var promises = []; 
    for (var i = 0; i < total; i++) { 
     var value = datas[i]; 
     promises.push(AddItems(value, Result)); 
    } 
    // Wait until they're all resolved... 
    $.when.apply($, promises).then(
     function() { 
      // ...and then call SendPDF 
      SendPDF(Result); 
     }, 
     function() { 
      // At least one of the ajax calls failed, handle it 
     } 
    ); 
} 

$.when.apply($, someArray)是看起来怪怪的符号,我们需要因为$.when预计许诺一个列表是一系列参数而不是单个数组。所以我们必须使用Function#apply来分散它们(在ES5和更早的版本中;在ES2015和更高版本中,我们可以使用扩展符号)。

0

首先,Javascript通常是单线程的;在跳转到执行队列中的另一个块之前,它会完全执行一个块。

现在你的代码,您呼叫SendPDF ProcessTable而不是它。如果您希望SendPDF在ProcessTable之后执行,请在调用ProcessTable的行的正下方调用它。不同的是,如果你这样做,那么SendPDF将在ProcessTable返回后执行,与当前代码不同。

每个Javascript开发人员需要注意的第二件事是从Javascript单线程出现的回调模式。请注意,所有这些成功的Ajax回调将不会在它们被解析/解释的同时执行! Javascript引擎将立即继续执行下一行,并且回调可能仅在将来的某个时刻执行。如果您想更好地理解这一点,请在ajax调用之前以及成功回调中放置日志消息。

+0

*在大多数常见环境中,“Javascript始终是单线程的......”。并非在所有环境中。 (例如:Nashorn,Rhino。)它不是一种语言,它是一种环境问题。 –

+1

感谢您的信息。不知道JS不运行单线程的环境。 – digitspro