2017-02-18 49 views
0

私は、ポストメソッドとデータテーブルを使用するプログラムを持っています。数週間の試練の後、私は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の関数呼び出しは他のすべての言語と同じように機能するので、これは特にJSとは関係ないと思います。これは、同期/非同期の誤解のように聞こえる。 – Carcigenicate

+0

そして私はあなたが持っている問題が何かを理解していません。 '問題は、プログラムがProcessTable関数の途中でSend関数を実行していることです。あなたは 'ProcessTable'から' SendPDF'を呼び出しているので、実行すると思います。どうしたの? – Carcigenicate

+0

あなたの問題はあなたの 'ProcessTable'関数で' AddItems(value、Result);を呼び出しています。ここでループはすべての 'AddItems'呼び出しの前に行われます。 – LGSon

答えて

1

しかし、JavaScriptがどのように機能を実行し、どのような順序で実行されるかを説明できる場合は、その順序を制御する方法。それは素晴らしいだろう。

JavaScript関数は他のほとんどの言語の関数と同じように機能します。関数を呼び出すと、関数は完了するまで実行され、制御は呼び出し元に戻ります。 (そして、ほとんどのJavaScript環境では、複数のスレッドについて心配する必要はありません.JavaScriptはシングルスレッド言語ではありませんが、使用されるほとんどの環境ではグローバル環境ごとにスレッドが1つしか使用されないため、

コード内の問題は、非同期です。コードではProcessResultsの真ん中に呼び出されません。 AddItemsへのすべての呼び出しが完了して返された後、最後の近くに呼び出されます。 しかし、あなたがAddItemsを呼び出し、それがあるんすべてにプロセス(ajaxリクエスト)それは、あなたのJavaScriptを実行しているスレッドとは別に、非同期を継続し始めます。したがってSendPDFと呼ばれ、の前にすべての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で待っている:それを修正する

、我々は$.ajaxは私たちに与えることを約束を返すAddItems持つことで、完全なものをAJAX呼び出しまで待ちますProcessResultsが戻った後)、後に起こる:$.whenは約束のリストを想定しているため

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)は、我々が必要と奇妙に見える表記で単一の配列ではなく、一連の引数を使用します。したがって、それらを広げるにはFunction#applyを使用する必要があります(ES5以前では、ES2015以降では、スプレッド表記を使用できます)。

0

まず、Javascriptは通常はシングルスレッドです。実行キュー内の別のブロックの実行にジャンプする前にブロックを完全に実行します。今

あなたのコードに、あなたはそれが後ProcessTableない内部SendPDF を呼んでいます。 SendPDFをProcessTableの後に実行する場合は、ProcessTableが呼び出された行のすぐ下でSendPDFを呼び出します。違いは、これを行うと、あなたの現在のコードで起こっていることとは異なり、SendPDFはProcessTableが返った後に実行されるということです。

Javascriptの開発者が気づく必要があるもう1つ目は、Javascriptからシングルスレッド化されたコールバックパターンです。成功したすべてのAjaxコールバックは、解析/解釈されると同時に実行されないことに注意してください。 Javascriptエンジンは直ちに次の行の実行を継続し、コールバックは将来のある時点でのみ実行されます。これをよりよく理解したい場合は、ajaxコールの直前と成功コールバックの内側にログメッセージを置いてください。

+0

* "ほとんどの一般的な環境で" Javascriptは常にシングルスレッドです "*。すべての環境ではありません。 (例:Nashorn、Rhino)言語のことではなく、環境のことです。 –

+1

情報ありがとうございます。 JSがシングルスレッドで動作しない環境は認識していませんでした。 – digitspro

関連する問題