等待所有请求完成

时间:2018-06-22 08:43:06

标签: javascript jquery

我正在建立网站,但有2个问题。我正在使用jQuery 3。

1)我正在发送2个AJAX请求,如果需要,我想从两个请求中获取信息。我正在使用这样的代码:

let ajaxCalls = [];

if (logoUploaded) {
    const sendPhoto = $.ajax({
        type: submit.data('ajax-logo-create-method').toUpperCase(),
        url: submit.data('ajax-logo-create-url'),
        headers: headers,
        data: {file: logo},
        dataType: 'json',
        success: function (data) {
            // here another request would be run
            sleep(500).then(() => {
                console.log('was sleeping 500 ms');
            });
            sleep(10000).then(() => {
                console.log('was sleeping 10000 ms');
            });
        }
    });
    ajaxCalls.push(sendPhoto);
}

const sendContactData = $.ajax({
    type: submit.data('ajax-data-method').toUpperCase(),
    url: submit.data('ajax-data-url'),
    headers: headers,
    data: data,
    dataType: 'json'
});

ajaxCalls.push(sendContactData);

$.when.apply(this, ajaxCalls).then(function () {
    hideValidationErrors();
    showSendStatusMessage('#' + submit.data('ajax-update-ok'));
    submit.removeClass('ajax-js-working');

}, function() {
    let validationErrors = [];
    $.each(ajaxCalls, function (index, ajaxCall) {
        if (ajaxCall.status === 422) {
            json = $.parseJSON(ajaxCall.responseText);
            console.log(json);
            $.each(json.errors, function (field, messages) {
                validationErrors.push({'field': field, 'messages': messages});
            });
        }
    });

    hideValidationErrors();

    if (validationErrors.length > 0) {
        $.each(validationErrors, function (id, object) {
            wrapper = $('#' + object.field + '-container');
            wrapper.addClass('error');
            displayValidationErrorMessages(wrapper, object.messages);
        });
    }

    showSendStatusMessage('#' + submit.data('ajax-update-error'));
    submit.removeClass('ajax-js-working');
});

但是不幸的是,在使用此代码时,$when .. then似乎仅在等待第一个失败的请求,我需要在这里将它们都包含在内。

2)第二个问题是我在第一个请求中成功完成了什么。在某些情况下,当此请求完成并且成功后,我将不得不运行另一个请求,并且在这种情况下,我希望在成功完成来自请求的情况下运行$.when.apply(this, ajaxCalls).then(function () {。有可能做到这一点吗?

如果可以的话,请给我完整的代码示例,以说明如何进行更改才能使其正常工作。

1 个答案:

答案 0 :(得分:0)

我最后要做的是像这样将开始和完成的请求添加到数组(ajaxCallsdoneAjaxCalls)中:

let ajaxCalls = [];
let doneAjaxCalls = [];

const fileInput = $('img#uploadedImg');

const fileExisted = fileInput.hasClass('imgExisted');
const fileWasRemoved = fileInput.hasClass('imgDeleted');
const fileWasUploaded = fileInput.hasClass('newImgUploaded');

const logo = fileInput.attr('src');

const needRemovePhoto = fileExisted && (fileWasRemoved || fileWasUploaded);

if (needRemovePhoto) {
    const removePhoto = $.ajax({
        type: submit.data('ajax-logo-delete-method').toUpperCase(),
        url: submit.data('ajax-logo-delete-url'),
        headers: headers,
        data: {file: logo},
        dataType: 'json',
        error: function (response) {
            doneAjaxCalls.push(response);
            handleMultipleAjaxCalls(submit, ajaxCalls, doneAjaxCalls);
        },
        success: function (response) {
            fileInput.removeClass('imgDeleted');
            fileInput.removeClass('imgExisted');
            if (fileWasUploaded) {
                const sendPhoto = $.ajax({
                    type: submit.data('ajax-logo-create-method').toUpperCase(),
                    url: submit.data('ajax-logo-create-url'),
                    headers: headers,
                    data: {file: logo},
                    dataType: 'json',
                    success: function (response) {
                        fileInput.addClass('imgExisted');
                    },
                    complete: function (response) {
                        doneAjaxCalls.push(response);
                        handleMultipleAjaxCalls(submit, ajaxCalls, doneAjaxCalls);
                    }
                });
            }
            else {
                doneAjaxCalls.push(response);
                handleMultipleAjaxCalls(submit, ajaxCalls, doneAjaxCalls);
            }
        }
    });
    ajaxCalls.push(removePhoto);
}
else if (fileWasUploaded) {
    const sendPhoto = $.ajax({
        type: submit.data('ajax-logo-create-method').toUpperCase(),
        url: submit.data('ajax-logo-create-url'),
        headers: headers,
        data: {file: logo},
        dataType: 'json',
        success: function (response) {
            fileInput.addClass('imgExisted');
        },
        complete: function (response) {
            doneAjaxCalls.push(response);
            handleMultipleAjaxCalls(submit, ajaxCalls, doneAjaxCalls);
        }
    });
    ajaxCalls.push(sendPhoto);
}

const sendContactData = $.ajax({
    type: submit.data('ajax-method').toUpperCase(),
    url: submit.data('ajax-url'),
    headers: headers,
    data: data,
    dataType: 'json',
    complete: function (response) {
        doneAjaxCalls.push(response);
        handleMultipleAjaxCalls(submit, ajaxCalls, doneAjaxCalls);
    }
});

ajaxCalls.push(sendContactData);

如您所见,在多种情况下,我先调用handleMultipleAjaxCalls函数,然后这样定义该函数:

window.handleMultipleAjaxCalls = function (submit, ajaxCalls, doneAjaxCalls) {
    // if not all expected requests were done (success or failure), do nothing
    if (doneAjaxCalls.length < ajaxCalls.length) {
        return;
    }

    // here we know that all expected AJAX requests were completed (success or failure)

    // here more logic after all requests are completed
});

因此,在更多情况下,我将执行此函数,因此可能会启动逻辑,如果所有已启动的ajaxcalls都真正完成(只是数组比较的简单长度),我将在此函数中进行比较