Можно ли предотвратить слишком много асинхронных вызовов с обещаниями? - PullRequest
0 голосов
/ 11 октября 2019

Я хочу загрузить контент на мою страницу с помощью $.ajax вызовов.

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

Я хотел бы вызвать Ajax-вызов, когда он равен * 1006. * полезно ... Значение, когда в данный момент не выполняется Ajax-вызов.

При первой загрузке Ajax-вызов выполняется немедленно. Кроме того, завершение предыдущего вызова Ajax может дать нам повод выполнить новый вызов Ajax.

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

Есть ли лучший способ написать это?

// This variable knows anytime if we are already trying to perform an asynchronous operation and should not ask for another
var lock = false;

// This function tells us if there is something async to do with our page
var thereIsSomethingAsyncToDo = function() {
    // returns true or false
}

// This function performs an asynchronous call, eg. $.ajax()
var doSomethingAsync = function() {
    // returns a Deferred object ?
}

// This function checks if it is the right time to perform an asynchronous operation
var shouldIDoSomething = function() {

    // If the lock is set, then we are already doing something, there is no use in queuing multiple requests that might end doing the same thing
    if (lock)
        return;
    // The lock is not set yet, so we can set it to ensure that every other call will be rejected
    lock = true;

    // Check if there is actually something to do
    if (thereIsSomethingAsyncToDo()) {
        // If there is something to do, chain the resolution of that something with a resolution
        $.when(doSomethingAsync(todo)).done(function() {
            // Release the lock
            lock = false;
            // Check if something else needs to be done
            shouldIDoSomething();
        });
    }
    // If there is nothing to do, simply release the lock
    else {
        lock = false;
    }

};

// Anytime the window is scrolled, we might need to do something
$(window).scroll(function() {
    shouldIDoSomething();
});

// When the page is first loaded we might need to do something
shouldIDoSomething();

1 Ответ

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

Сначала я бы написал вашу основную логику, т. Е. doSomethingAsync() в вашем примере, не думая о вашем механизме блокировки.

async function doSomethingAsync () {
  try {
    if (!thereIsSomethingAsyncToDo()) return;

    const results = await $.ajax('/api/json', { dataType: 'json' });
    // append content to DOM
  } catch (error) {
    // handle error
  }
}

После того как вы закончите с этим, используйте следующую фабрикуфункция для предотвращения повторного запуска базовой базовой логики, пока предыдущий вызов все еще ожидает:

function lock (fn) {
  let pending = false;

  return async () => {
    if (pending) return;

    try {
      pending = true;
      await fn();
    } finally {
      pending = false;
    }
  };
}

const doSomethingAsyncAndLock = lock(doSomethingAsync);

Наконец, вы хотите, чтобы событие прокрутки вызывало эту новую функцию:

$(window).scroll(() => {
  doSomethingAsyncAndLock();
});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...