确保javascript函数按特定顺序执行

时间:2017-02-18 16:18:37

标签: javascript jquery ajax model-view-controller datatables

我有一个使用ajax post方法和dataTables的程序。摆弄了几个星期之后,我确定我根本不明白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 个答案:

答案 0 :(得分: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期望一个promises列表作为一系列参数而不是单个数组。所以我们必须使用Function#apply来展开它们(在ES5及更早版本中;在ES2015及更高版本中,我们可以使用扩展符号)。

答案 1 :(得分:0)

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

现在,对于您的代码,您在 ProcessTable中调用SendPDF ,而在之后调用。如果希望SendPDF在ProcessTable之后执行,请在调用ProcessTable的行的正下方调用它。不同之处在于,如果执行此操作,则SendPDF将在ProcessTable返回后执行,这与当前代码所发生的情况不同。

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