Вызовите функцию JavaScript, когда все вызовы Ajax завершены - PullRequest
0 голосов
/ 31 марта 2020

нужна помощь с кодом JavaScript, который не работает должным образом.

Приложение отправляет имена файлов на сервер с помощью Ajax вызовов, которые необходимо обработать, но я хочу сообщить базе данных, что текущий импорт был завершен, когда все они сделаны. Проблема, с которой я столкнулся, заключается в том, что код для обновления базы данных с состоянием запускается до выполнения любого из вызовов ajax.

Я уже готов в ряде областей в сети, что вы могли бы потенциально создать массив обещаний, чтобы отследить это, но, честно говоря, JavaScript, будучи моим слабым местом, я не уверен, как это сделать go о его реализации.

ниже приведены мои текущие фрагменты кода:

функция, которая перебирает имена файлов:

function importFiles() {
    serverImporterInit();
    let files = getFiles();
    if (files) {
        showImportProgressModal(files);
        let looper = $.Deferred().resolve();
        $.when.apply($, $.map(files, function (file, index) {
            let fileStatusElement = document.getElementById('file-' + index + '-status');
            let fileErrorElement = document.getElementById('file-' + index + '-error');
            looper = looper.then(function () {
                setTimeout(function () {
                    return import_file_request(file, fileStatusElement, fileErrorElement);
                }, 2000);
            });
            return looper;
        })).then(function () { 
        });
    }
}

ajax вызов сервера:

function import_file_request(file, element, errorElement) {
    let deferred = $.Deferred();
    fileImportStatusInProgress(element);
    $.ajax({
        type: 'POST',
        url: '/importer/manual_import',
        data: {'file': file.toString()},
        success: function(data) {
            fileImportStatusSuccess(element);
            deferred.resolve(data);
        },
        error: function (error) {
            fileImportStatusFailed(error, element, errorElement);
            deferred.reject(error);
        }
    });

    return deferred.promise();
}

Обе эти функции были получены из других учебных пособий в Интернете, но я не совсем уверен, что они когда-либо делали то, что я изначально планировал, поскольку я только что нашел способ попытаться отследить состояние завершения из-за другого требования.

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

Обновление Я попытался обновить код, чтобы использовать массив обещаний, но все еще не повезло.

Файл l oop:

const importFiles = async (files) => {
    serverImporterInit()
    const filesLength = files.length
    showImportProgressModal(files);
    for (let i = 0; i < filesLength; i++) {
        const requests = files.map((file) => {
            let fileStatusElement = document.getElementById('file-' + i + '-status');
            let fileErrorElement = document.getElementById('file-' + i + '-error');
            return import_file_request(file, fileStatusElement, fileErrorElement) // Async function to import file
            .then(console.log(file + " successfully imported"))
            .catch(e => console.log('Error'))
    })
        await Promise.all(requests)
        .then(serverImporterClose())
        .catch(e => console.log(''))
    }
}

Запрос на импорт файла на сервер:

function import_file_request(file, element, errorElement) {
    fileImportStatusInProgress(element);
    return new Promise((resolve, reject) => {
        $.ajax({
            type: 'POST',
            url: '/importer/manual_import',
            data: {'file': file.toString()},
            success: function(data) {
                fileImportStatusSuccess(element);
                resolve();
            },
            error: function (error) {
                fileImportStatusFailed(error, element, errorElement);
                reject();
            }
        });
    })
}

1 Ответ

0 голосов
/ 01 апреля 2020

Вы, похоже, используете jQuery, поэтому я пытаюсь дать решение на основе jQuery без нативного обещания. Я думаю, вам следует либо использовать встроенное обещание в сочетании со встроенной функцией fetch(), но не jQuery или jQuery в одиночку.

Ключом является использование $.map() для возврата массива обещаний и затем дождитесь их всех, используя $.when(). Также всегда важно вернуть обещание jQuery.

function importFiles() {
  var files = getFiles();
  if (files) {
    showImportProgressModal(files);
    serverImporterInit();
    var promises = $.map(files, function(file, index) {
      let fileStatusElement = document.getElementById('file-' + index + '-status');
      let fileErrorElement = document.getElementById('file-' + index + '-error');

      return import_file_request(file, fileStatusElement, fileErrorElement)
    })
    $.when.apply($, promises).then(function(results) {
      serverImporterClose();
      results.forEach(function(result) {
        if (result) {
          console.log("yay, success");
        }
        else {
          console.log("failed");
        }
      })
      hideImportProgressModal(files);
    });
  }
}

function import_file_request(file, element, errorElement) {
    fileImportStatusInProgress(element);
    // MUST return the promise here
    return $.ajax({
        type: 'POST',
        url: '/importer/manual_import',
        data: {'file': file.toString()},
        success: function(data) {
            fileImportStatusSuccess(element);
            return true;
        },
        error: function (error) {
            fileImportStatusFailed(error, element, errorElement);
            return false;
        }
    });
}

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