【问题标题】:Display loading spinner if function takes longer than X milliseconds如果函数花费的时间超过 X 毫秒,则显示加载微调器
【发布时间】:2021-06-13 07:44:59
【问题描述】:

我想显示一个加载微调器,但前提是“my_code_here”的执行时间超过 X 毫秒。

我已经做到了:

<button onClick='my_long_function()'></button>
<div class="spinner" style="display: none;"></div>
my_long_function: function()
{
    $(".spinner").show(200, function()
    {
        my_code_here
        my_code_here
        my_code_here

        $(".spinner").hide();
    }
}

它可以工作,但即使代码花费不到 100 毫秒,它也会显示微调器,所以它会在眨眼间出现,我在让它看起来不错时遇到问题。

请注意,等待服务器响应的不是 ajax,而是客户端。

我通过阅读类似 5 个 stackoverflow 问题尝试了 setTimeout 和 clearTimeOut 的内容,但它似乎没有触发或微调器永远停留。

【问题讨论】:

  • 由于 javascript 是单线程的,我认为你可以做到这一点的唯一方法是在有自己的线程并使用 setTimeout 的 web worker 中运行该函数。
  • 我很困惑,你想在 x 毫秒后显示微调器,对吗?所以let timeout = setTimeout(showSpinner, x); 然后在你长时间运行的代码中,最后是clearTimeout(timeout); hideSpinner();。如果timeout 已经过去,那么clearTimeout 无关紧要,如果showSpinnerhideSpinner 是幂等的(即,在隐藏的微调器上运行 hideSpinner 不会做任何事情),你应该很好。
  • 如果都是 js,那么唯一的方法就是在你的 my_code_here 中有一些东西来触发显示(例如在 x 次迭代或比较 current_time-start-time &gt; timeout - within你的代码。
  • 您的代码将按原样制作 200 毫秒以上的动画效果然后开始您的 my_code_here。将超时更改为类似(例如 2000)并输入一些简单的内容,例如 my_code(例如 console.log("start")),您就会看到发生了什么。
  • @HereticMonkey 我一直这样做,但它从来没有显示微调器(我认为它可能在瞬间出现和消失)。

标签: javascript jquery


【解决方案1】:

https://jsfiddle.net/w9khvx50/1/

const loader = document.querySelector('.loader');
const status = document.querySelector('.status');

// This function simply emulates an asynchronous function
const wait = (ms = 5000) => {
    return new Promise((resolve) => {
    setTimeout(() => {
        resolve();
    },ms)
  })
}

const toggleLoader = (state) => {
    loader.classList.toggle('show', state);
}


const timeout = setTimeout(toggleLoader, 2000);

status.textContent = "Starting load function";
wait(4000)
.then(() => {
    status.textContent = "Load function complete";
    toggleLoader(false);
        clearTimeout(timeout);
})
.loader {
  border: 16px solid #f3f3f3;
  border-radius: 50%;
  border-top: 16px solid #3498db;
  width: 120px;
  height: 120px;
  animation: spin 2s linear infinite;
  opacity: 0;
}

.loader.show {
  opacity: 1;
}

@keyframes spin {
  0% { transform: rotate(0deg); }
  100% { transform: rotate(360deg); }
}
<div>
  <div class="loader"></div>
  <div class="status"></div>
</div>

这里最好的方法是清除超时,我想你之前一定是错误地实现了它。如果const timeout中的ms小于wait的时间,就会显示加载器。

请注意,如果您正在执行的函数不是异步的,那么您需要调查 Web Workers,因为您的函数将阻塞主线程并且不会执行其他任何操作(例如运行超时回调)。您应该创建一个网络工作者,将您的长函数委托给它,然后如果您在时间结束之前收到完整的消息,则清除超时。

【讨论】:

  • 这与我当前的代码确实不同,我有点迷茫,但谢谢你,会分析一下(也检查了一点关于网络工作者)
猜你喜欢
  • 2013-08-11
  • 1970-01-01
  • 2021-08-09
  • 1970-01-01
  • 2023-03-09
  • 2016-05-22
  • 1970-01-01
  • 2015-04-17
  • 1970-01-01
相关资源
最近更新 更多