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

标签 javascript jquery ajax model-view-controller datatables

我有一个使用 ajax post 方法和数据表的程序。经过几周的摆弄,我确定我根本不明白 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 如何执行函数以及以什么顺序执行。以及如何控制该顺序。那太好了。

最佳答案

But if you could explain how javascript executes functions, and in what order. And how to control that order. That would be great.

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

您的代码中的问题是异步性。在您的代码中,SendPDF 不会在 ProcessResults 中间调用;在所有对 AddItems 的调用完成并返回之后,它会在接近尾声时被调用。 但是,当您调用AddItems时,它所做的只是启动一个进程(一个ajax请求),然后继续异步,与运行 JavaScript 的线程分开。因此,SendPDF 在所有这些 ajax 调用有机会完成之前被调用。

为了解决这个问题,我们通过让 AddItems 返回 $.ajax 给我们的 promise 来等待这些 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 中等待,直到所有这些 promise 都得到解决(这会在 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 期望将 Promise 列表作为一系列参数作为单个数组。因此我们必须使用 Function#apply 来展开它们(在 ES5 及更早版本中;在 ES2015 及更高版本中,我们可以使用展开表示法)。

关于javascript - 确保 javascript 函数按特定顺序执行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42317583/

相关文章:

javascript - 为什么 event.preventDefault() 并不总是有效?

javascript - 如何在没有图像和通过属性的情况下在jquery中计算li

ajax - MVC3 Ajax 子 Action

javascript - 如何使 discord bot 的命令不区分大小写

javascript - Jquery 滚动到基于数据属性的部分

jquery - 使用MVC3的HTML编码和解码

jquery - jQuery attr() 在更改时不会更新其值

javascript - jQuery AJAX get请求无法正常工作且返回值无法在控制台显示

javascript - 是否可以在 ES6 项目中使用自定义类型定义?

javascript - 数组排序有两个要求