Как прервать зацикленный AJAX-запрос к контроллеру MVC (редактирование из-за отсутствия соответствующего ответа) - PullRequest
0 голосов
/ 23 октября 2011

Я хочу отправить файловые блоки на сервер, асинхронный с сервером (действие MVC в контроллере). Я хочу убедиться, что запросы, которые я отправляю через JS, могут быть отменены на полпути. Я знаю о AJAX abort (), но я думаю, что поскольку запросы асинхронные, у меня есть небольшая опция, кроме установки переменной Session на контроллере MVC, которая отклоняет все блоки, поступающие в него после установки. Пожалуйста, скажите мне оптимальный способ сделать это. Можете ли вы сказать мне, может ли abort () использоваться в этом сценарии, и если да, то как? Каковы другие стратегии, которым я могу следовать, чтобы сделать это лучше?

Мой метод JS:

$.ajax({
    type: "POST",
    context: this,
    async: true,
    url: "/Home/PrepareMetaData",
    data: { "blocksCount": totalNumberOfBlocks, "fileName": file.name, "fileSize": file.size },
    dataType: "json",
    error: function () {
        statusLabel.innerHTML = 'Failed to send file meta data. Retry after some time.';
        progressElement.setAttribute('hidden', 'hidden');
    },
    success: function () {
        var start = 0;
        var end = Math.min(blockLength, file.size) - 1;
        var incrimentalIdentifier = 1;
        while (start <= file.size - 1 && !window.haltExecution) {
            var data = new FormData();
            data.append(incrimentalIdentifier, file.webkitSlice(start, end));
            xhr = $.ajax({
                async: true,
                url: '/Home/UploadBlock',
                context: this,
                data: data,
                cache: false,
                contentType: false,
                processData: false,
                type: 'POST',
                error: function (notice) {
                    statusLabel.innerHTML = notice;
                    progressElement.setAttribute('hidden', 'hidden');
                    haltExecution = true;
                },
                success: function (notice) {
                    blockCounter += 1;
                    if (notice.error || notice.isLastBlock) {
                        this.message = notice.message;
                    }

                    if (notice.error || blockCounter == totalNumberOfBlocks) {
                        statusLabel.innerHTML = this.message;
                        progressElement.setAttribute('hidden', 'hidden');
                        haltExecution = true;
                    }
                }
            });

            start = end + 1;
            end = Math.min(start + blockLength, file.size) - 1;
            incrimentalIdentifier++;
        }
    }
});

Спасибо.

Edit: Я согласен с комментариями, но если я сделаю запрос Ajax синхронным, то я буду идти против природы Ajax, а также риску снижения производительности. Другая проблема будет зависать пользовательского интерфейса. Даже если бы я использовал Web Worker для этого, мой код стал бы асинхронным, как сейчас. Каковы ваши взгляды ??

Ответы [ 2 ]

1 голос
/ 26 октября 2011

Вот переписать, который должен указать вам в правильном направлении. Вам нужно отправлять каждый последующий блок в обработчике успеха предыдущего, а не отправлять их все сразу. Это просто быстрый взлом того, что у вас уже было, поэтому он не идеален, но это должно помочь.

var sendFile = function(){
    var start = 0;
    var end = Math.min(blockLength, file.size) - 1;
    var incrimentalIdentifier = 1;
    // I assume the following variables are in scope already:
    // file, blockCounter, haltExecution
    var sendNextChunk = function(){
        var data = new FormData();
        data.append(incrimentalIdentifier, file.webkitSlice(start, end));
        xhr = $.ajax({
            async: true,
            url: '/Home/UploadBlock',
            context: this,
            data: data,
            cache: false,
            contentType: false,
            processData: false,
            type: 'POST',
            error: function (notice) {
                statusLabel.innerHTML = notice;
                progressElement.setAttribute('hidden', 'hidden');
                haltExecution = true;
            },
            success: function (notice) {
                blockCounter += 1;
                if (notice.error || notice.isLastBlock) {
                    this.message = notice.message;
                }

                if (notice.error || blockCounter == totalNumberOfBlocks) {
                    statusLabel.innerHTML = this.message;
                    progressElement.setAttribute('hidden', 'hidden');
                    haltExecution = true;
                    return; // We are finished sending I assume?
                }

                start = end + 1;
                end = Math.min(start + blockLength, file.size) - 1;
                incrimentalIdentifier++;

                // Send the next block.
                sendNextChunk();
            }
        });
    };

    //Start sending:
    sendNextChunk();
};

$.ajax({
    type: "POST",
    context: this,
    async: true,
    url: "/Home/PrepareMetaData",
    data: { "blocksCount": totalNumberOfBlocks, "fileName": file.name, "fileSize": file.size },
    dataType: "json",
    error: function () {
        statusLabel.innerHTML = 'Failed to send file meta data. Retry after some time.';
        progressElement.setAttribute('hidden', 'hidden');
    },
    success: sendFile
});
0 голосов
/ 23 октября 2011

Если вы используете асинхронную опцию, вы не можете запускать js до тех пор, пока запрос не будет выполнен (с ошибкой или нет), поэтому единственное решение - отменить со стороны сервера или не использовать асинхронную работу.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...