AJAX调用不在服务器端执行,与客户端调用的顺序相同

时间:2015-08-04 02:59:55

标签: javascript ajax asp.net-mvc

我在视图中有一个带有以下javascript函数的ASP.NET MVC应用程序:

function OnAmountChanged(s, fieldName, keyValue, url) {
    console.log("Get Number: " + s.GetNumber());
    console.log(" ");
        $.ajax({
            type: "POST",
            url: url,
            data: { key: keyValue, field: fieldName, value: s.GetNumber() },
            success: function () {
                reloadShoppingCartSummary();
            }
        });
}

使用向上/向下按钮,我可以增加/减少每次点击调用此功能的字段数。 使用console.log,我可以看到以正确的顺序调用JavaScript函数(我更改了数字值的顺序)。 但是通过在服务器端调试,我注意到它执行调用的顺序是不同的。 什么可能导致这个问题? 我该如何解决或解决这个问题?

1 个答案:

答案 0 :(得分:4)

这并不奇怪,也不是你所期待的。如果您希望按特定顺序处理请求,则必须发送一个请求,等待响应,然后发送下一个请求。您不能只发送所有这些内容并期望按特定顺序处理它们。

在您的特定情况下,如果请求是“正在进行中”,则您必须禁用该按钮,否则您将排队下一个请求并在上一个请求完成时将其播放。

还有各种策略可用于发送可以阻止,适应或检测不按顺序问题的数据,但使用哪些以及如何使用这些策略取决于您发送的特定数据及其工作原理事物的客户端和服务器端。

有许多可能的编码策略来处理这个问题。这是一种方法,在另一个请求正在进行时对任何请求进行排队,迫使服务器按顺序处理它们:

var changeQueue = [];
changeQueue.inProcess = false;
function OnAmountChanged(s, fieldName, keyValue, url) {
    // if already processing a request, then queue this one until the current request is done
    if (changeQueue.inProcess) {
        changeQueue.push({s:s, fieldName: fieldName, keyValue: keyValue, url: url});
    } else {
        changeQueue.inProcess = true;
        console.log("Get Number: " + s.GetNumber());
        console.log(" ");

            $.ajax({
                type: "POST",
                url: url,
                data: { key: keyValue, field: fieldName, value: s.GetNumber() },
                success: function () {
                    reloadShoppingCartSummary();
                }, complete: function() {
                    changeQueue.inProcess = false;
                    if (changeQueue.length) {
                        var next = changeQueue.shift();
                        OnAmountChanged(next.s, next.fieldName, next.keyValue, next.url);
                    }
                }
            });
        }
}

仅供参考,我认为我们可能会承诺为我们排队工作,但我正在制定一些细节。这是一个正在进行中的想法:http://jsfiddle.net/jfriend00/4hfyahs3/。如果您快速按下该按钮多次,您可以看到它按下排队并按顺序处理它们。

以下是通用承诺序列化程序的具体想法:

// utility function that works kind of like `.bind()`
// except that it works only on functions that return a promise
// and it forces serialization whenever the returned function is called
// no matter how many times it is called in a row
function bindSingle(fn) {
    var p = Promise.resolve();

    return function(/* args */) {
        var args = Array.prototype.slice.call(arguments, 0);

        function next() {
            return fn.apply(null, args);
        }

        p = p.then(next, next);
        return p;
    }
}

function OnAmountChanged(s, fieldName, keyValue, url) {
    console.log("Get Number: " + s.GetNumber());
    console.log(" ");
    return $.ajax({
        type: "POST",
        url: url,
        data: { key: keyValue, field: fieldName, value: s.GetNumber() }
    }).then(reloadShoppingCartSummary);
}

var OnAmountChangedSingle = bindSingle(OnAmountChanged);

因此,要使用此代码,您可以将OnAmountChangedSingle传递给事件处理程序而不是OnAmountChanged,这将强制序列化。