Выполнять AJAX-вызов, только если не выполняется другой AJAX-запрос от предыдущего вызова функции - PullRequest
0 голосов
/ 04 октября 2019

Я попал на новую грязную базу кода без какого-либо тестирования, и я довольно долго борюсь с этой проблемой. Я не могу использовать любой код ES6, просто старый ванильный JS и jQuery.

Контекст: на веб-странице есть несколько пар входов, первый вход из пары вызывает firstFunction() при размытии, а второй ввод secondFunction() также при событии размытия. Как видно из примера кода ниже, каждая функция затем вызывает другую функцию, ajaxFunction(), которая выполняет запрос AJAX.

Цель: я хочу иметь возможность вызывать ajaxFunction() только в том случае, если не выполняется другой запрос AJAX от предыдущего вызова функции. Дело в том, что когда он запускается впервые на паре входов, в базе данных создается новая строка, и запрос возвращает идентификатор строки. Поэтому, когда он вызывается во второй раз, он будет ОБНОВЛЕНИЕ в базе данных вместо вставки из-за идентификатора. Если второй вызов из пары выполняется до того, как первый завершится, у меня останутся две отдельные строки в базе данных, что нежелательно.

Пример: если пользователь вводит какой-то текст в первый ввод, тоfirstFunction() срабатывает при размытии, затем он быстро перемещается ко второму входу и вводит что-то, так что secondFunction() запускается при размытии, но может случиться так, что AJAX-запрос от вызова firstFunction() не былзавершено еще. Таким образом, вызов AJAX из secondFunction() должен начинаться только в том случае, если был завершен вызов из firstFunction(). Та же логика применима для случая, когда пользователь начинает вводить данные во втором вводе и вводе в первом.

Примечание: это не единственные запросы AJAX на странице, есть и несколько других.

Я провел какое-то исследование и чувствую, что $.when() - это то, что мне нужно, но это меня беспокоит, когда дело доходит до его интеграции в эту логику. Я также думал о $.active, но это не очень помогает.

function firstFunction() {
    // Some logic goes here then we call the AJAX function. 
    ajaxFunction(1, 2, 3);
}

function secondFunction() {
    // Some logic goes here then we call the AJAX function. 
    ajaxFunction(4, 5, 6);
}

function ajaxFunction(param1, param2, param3) {
    $.ajax({
        method: "POST",
        url: "https://website.localhost",
        data: { 
            param1: param1
            param2: param2
            param3: param3
        }
    }).done(function() {
        console.log('Done!');
    });
}

Ответы [ 4 ]

2 голосов
/ 04 октября 2019

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

Это было очень хорошо объяснено @gnarf на этот ответ .

1 голос
/ 04 октября 2019

Это быстрый способ сделать очередь, есть способы сделать ее чище, но это базовая концепция

function firstFunction() {
  addToQueue({
    param1: 1,
    param1: 2,
    param1: 3
  });
}

function secondFunction() {
  addToQueue({
    param1: 1,
    param1: 2,
    param1: 3
  });
}


var activeQueue = []
var activeRequest = false

function addToQueue(data) {
  // Add item to the queue of things needing to run
  activeQueue.push(data);
  // if the request is not active than run it
  if (!activeRequest) {
    executeQueue()
  }
}

function executeQueue() {
  // if nothing to run, exit
  if (!activeQueue.length) return
  // set the request is active
  activeRequest = true
  // get the data for this request
  var data = activeQueue.shift()
  // make the call
  $.ajax({
    method: "POST",
    url: "https://website.localhost",
    data: data
  }).done(function() {
    console.log('Done!');
    // mark call is done
    activeRequest = activeQueue.length > 0
    // run it again
    executeQueue()
  });
}
0 голосов
/ 04 октября 2019

Зависит от того, что вы хотите.

  1. Если все запросы ajax должны полностью игнорироваться, когда запрос ajax уже находится в полете, то:
var ajaxFuntion = (function() {
    var inFlight = null;
    return function(param1, param2, param3) {
        if(!inFlight) {
            inFlight = $.ajax({
                'method': "POST",
                'url': "https://website.localhost",
                'data': { 
                    'param1': param1,
                    'param2': param2,
                    'param3': param3
                }
            }).done(function(val) {
                inFlight = null;
            });
        };
        return inFlight;
    };
})();
Если запросы ajax должны быть поставлены в очередь на те, которые были ранее поставлены в очередь (любые из которых могут быть в полете), то:
var ajaxFuntion = (function() {
    var inFlight = jQuery.when(); // dummy starter promise.
    return function(param1, param2, param3) {
        inFlight = inflight.then(function() {
            return $.ajax({
                'method': "POST",
                'url': "https://website.localhost",
                'data': { 
                    'param1': param1,
                    'param2': param2,
                    'param3': param3
                }
            });
        };
        return inFlight;
    });
})();

Как видите, обе версии включают в себя IIFE , который возвращает функцию.

При использовании IIFE переменная inFlight является «самодостаточной», что исключает необходимость использования другого члена в той же области, что и ajaxFuntion или выше.

Во второй версии обратите внимание, что организация очередей действительно проста, поскольку jQuery.ajax() возвращает обещание, позволяющее формировать очередь путем объединения в цепочку .then().then().then() столько раз, сколько вам нужно.

0 голосов
/ 04 октября 2019

Если вы не хотите разрешить создание другого ajax, если он уже выполняется и еще не завершен (с ошибкой или успехом), просто создайте глобальную переменную bool, например:

var ajaxInProgress = false.

Вы можете установить значение true в ajaxFunction и установить значение false при завершении ajax. Затем вы помещаете свой AJAX-вызов в if(!ajaxInProgress) {...}.

Таким образом, вы не будете делать второй AJAX-вызов, если он уже сделан.

Я подозреваю, что вы хотите поставить свойajax вызывает в очереди, так что если вы сделаете что-то вроде:

firstFunction();
secondFunction();

Ваша вторая функция отправит ajax, но только после первого завершения. Чтобы это произошло, я бы написал для вашего кода простую очередь:

var queue = [];
var ajaxInProgress = false;

function ajaxFunction(param1, param2, param3) {
  if (!ajaxInProgress) {
    ajaxInProgress = true;
    $.ajax({
      method: "POST",
      url: "https://website.localhost",
      data: {
        param1: param1,
        param2: param2,
        param3: param3
      }
    }).done(function () {
      console.log('Done!');
      ajaxInProgress = false;
      executeNextAjaxInQueue();
    });
  } else {
    ajaxInProgress.push([param1, param2, param3]);
  }
}

function executeNextAjaxInQueue(ajaxParams) {
  if (queue.length === 0) {
    return;
  }

  var params = queue.shift();
  ajaxFunction(params[0], params[1], params[2]);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...