2017-02-18 6 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(); 
       } 
      }); 
     } 

Проблемы я имею что программа выполняет функцию SendPDF в середине функции ProcessTable. Я попытался остановить это, используя оператор if, но он все еще выполняется.

Если вы знаете, как исправить мой код, отлично. Но если бы вы могли объяснить, как javascript выполняет функции и в каком порядке. И как контролировать этот порядок. Это было бы прекрасно.

+2

Я не думаю, что это имеет какое-то отношение к JS, поскольку afaik выполняет функции JS как те же, что и на любом другом языке. Это больше похоже на недоразумение sync/async. – Carcigenicate

+0

И я не понимаю, в чем проблема. «Проблема, с которой я столкнулась, заключается в том, что программа выполняет функцию« Отправить PDF »в середине функции ProcessTable.». Вы вызываете 'SendPDF' из' ProcessTable', хотя я бы ожидал, что он будет запущен. В чем проблема? – Carcigenicate

+0

Ваша проблема заключается в вызове 'AddItems (value, Result);' в вашей 'ProcessTable' функции, где цикл будет выполнен до всех вызовов' AddItems'. – LGSon

ответ

1

Но если бы вы могли объяснить, как javascript выполняет функции и в каком порядке. И как контролировать этот порядок. Это было бы прекрасно.

Функции JavaScript работают точно так же, как и функции на большинстве других языков: когда вы вызываете функцию, она заканчивается, а затем управляет возвратом туда, откуда вы ее вызывали. (И в большинстве средах JavaScript вам даже не нужно беспокоиться о нескольких потоках, потому что, хотя JavaScript не является однопоточным, большинство сред, в которых он используется, используют только один поток для глобальной среды, что значительно увеличивает жизнь проще).

Вопрос в коде asynchronicity. В вашем коде 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 ожидает список обещает s ряд аргументов вместо одного массива. Поэтому мы должны использовать Function#apply для их распространения (в ES5 и более ранних версиях, в ES2015 и выше мы могли бы использовать разметку).

0

Прежде всего, Javascript обычно однопоточный; он полностью выполняет блок, прежде чем он перейдет к выполнению другого блока в своей «очереди выполнения».

Теперь ваш код, вы звоните SendPDF внутри ProcessTable и не после его. Если вы хотите, чтобы SendPDF выполнялся после ProcessTable, вызовите его прямо под строкой, где вызывается ProcessTable.Разница в том, что если вы это сделаете, то SendPDF будет выполняться после возврата ProcessTable, в отличие от того, что происходит с вашим текущим кодом.

Вторая вещь, о которой должен знать каждый разработчик Javascript, - это шаблон обратных вызовов, который возникает из того, что Javascript является однопоточным. Имейте в виду, что все эти успешные обратные вызовы ajax не будут выполняться одновременно с их анализом или интерпретацией! Механизм Javascript немедленно продолжит выполнение следующей строки, и обратные вызовы могут выполняться только в какой-то момент в будущем. Если вы хотите понять это лучше, поместите сообщения журнала прямо перед этими вызовами ajax, а также внутри обратных вызовов успеха.

+0

* «Javascript всегда однопоточный ...» * в большинстве обычных сред. Не во всех средах. (Примеры: Нашорн, Носорог.) Это не язык, а окружающая среда. –

+1

Спасибо за информацию. Не знал о средах, в которых JS не работает однопоточно. – digitspro

Смежные вопросы