2017-02-18 88 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