【问题标题】:Is it possible to prevent too many async calls with promises?是否可以通过 Promise 防止过多的异步调用?
【发布时间】:2019-10-11 01:46:51
【问题描述】:

我想通过$.ajax 调用将内容加载到我的页面中。

只要我滚动,新内容可能就会出现。但是,当我滚动页面时会触发许多滚动事件,我不希望每个事件都触发 Ajax 调用。

我想在它有用时触发 Ajax 调用...意思是,当当前没有 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();

【问题讨论】:

  • 这是否旨在类似于无限滚动机制?
  • 是的,它是无限滚动,你当场抓住了我
  • 似乎您想要某种形式的去抖动和/或节流。我假设 jQuery 已经有了这个,或者有一个插件,或者你可以使用另一个库,比如 lodash。很少值得重新滚动。
  • benalman.com/projects/jquery-throttle-debounce-plugin 读取,似乎去抖动和节流模式都意味着延迟。我不想在这里耽误任何事情,我正试图在前一个接听电话后立即开始新的通话。或者这是一件坏事?

标签: jquery asynchronous promise


【解决方案1】:

我将首先编写您的基本逻辑,即您示例中的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();
});

【讨论】:

    猜你喜欢
    • 2011-08-27
    • 1970-01-01
    • 1970-01-01
    • 2014-09-20
    • 2019-01-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多