【问题标题】:Is there a way for function to stop execution until the setTimeout() time is over有没有办法让函数停止执行,直到 setTimeout() 时间结束
【发布时间】:2021-11-01 17:58:03
【问题描述】:

我有一个简单的代码,如下面的 sn-p,每当单击按钮并显示警报时都会发出警报,运行正常但有某些缺点(知道这就是 setTimeout 的工作原理)。
在这里,当您单击按钮 2、3、4 次时,只会显示多次警报。但我只希望从第一次点击开始发出 1 次警报,并忽略进一步的点击,直到第一次点击完成 3 秒。

function alertBtn() {
  setTimeout(alertFunc, 3000);
}

function alertFunc() {
  alert("Alert is clicked so remain alerted");
}
<button onclick="alertBtn()">Alert me</button>

是否可以使用纯 JavaScript 方式?这可能类似于 SO 使用的方法,例如我们无法在 5 秒(或其他时间)内再次发表评论,该按钮在该时间间隔内有点禁用。 5秒的障碍

【问题讨论】:

  • 如何使用帮助程序来绑定点击处理程序,例如 lodash 的 before()
  • 您可能必须在 setTimeout() 回调中完成所有剩余的 javascript。
  • @EliranMalka 是否可以使用纯 JavaScript 停止调用该函数,直到第一次点击时间完成。
  • @user1599011 不明白你的意思。你能详细说明一下吗
  • 能否在超时结束前禁用按钮?

标签: javascript function settimeout


【解决方案1】:

您可以使用clearTimeout() 来取消先前通过调用setTimeout() 建立的超时

let time;
let clicked = false;
function alertBtn() {
  if (!clicked){
    clicked = true;
    clearTimeout(time);
    time = setTimeout(alertFunc, 3000);
  }
} 

function alertFunc() {
  alert("Alert is clicked so remain alerted");
  clicked = false;
}
<button onclick="alertBtn()">Alert me</button>

clearTimeout - https://developer.mozilla.org/en-US/docs/Web/API/clearTimeout

Debouncing and throttling in JavaScript

【讨论】:

  • 感谢 Ran 提供了很好的简单解决方案。想到这一点,但它有一些不同的功能,如 alert 直到最后一次点击的 3 秒才会发生,但我想在第一次点击后 3 秒后发生
  • 我修改了答案,希望这是你要找的(:
  • @RanTurner 不。敲击按钮时仍然不显示警报。
  • 再试一次。我检查了很多次
  • 好的,现在可以了:D
【解决方案2】:

听起来您正在寻找一种叫做节流的东西。这是一个如何实现它的示例:

const throttle = function (fn, delay) {
    let timeout;
    return function (...args) {
        if (!timeout) {
            const returnVal = fn.apply(this, args);

            timeout = setTimeout(() => {
                timeout = undefined;
            }, delay);
            
            return returnVal;
        }
    };
};

throttle 函数允许您将普通函数转换为 节流 函数,该函数只会在给定的 delay 时间(以毫秒为单位指定为匹配setTimeout的行为)。

它通过创建一个新函数来工作,该函数在第一次调用时设置超时,并调用初始函数。然后,如果在超时结束之前再次调用了受限制的函数,它将不会再次调用初始函数。

如果您想将函数限制 3 秒,那么您应该将值 3000 作为 delay 参数传递,以便创建的超时持续 3 秒。您可以通过将匿名函数传递给 throttle 来仅创建节流函数,如下所示:

const throttle = function (fn, delay) {
    let timeout;
    return function (...args) {
        if (!timeout) {
            const returnVal = fn.apply(this, args);

            timeout = setTimeout(() => {
                timeout = undefined;
            }, delay);
            
            return returnVal;
        }
    };
};

const alertBtn = throttle(function () {
  alert("Alert is clicked so remain alerted");
}, 3000);
<button onclick="alertBtn()">Alert me</button>

【讨论】:

  • 谢谢你这么好的答案,我从 JavaScript 室得到了同样的答案,但认为必须有一些简单的或其他方式,因为它对我来说有点复杂。但是在这里你 sn-p 在第一次点击 alert 是即时的。
  • 对不起,我当时可能误解了你的问题。我以为您希望第一次单击起作用,但是在它再次起作用之前会有 3 秒的“冷却”时间?对不起,如果我误解了你。如果您希望在自上次尝试调用该函数后经过冷却期后才触发该函数,这称为 debouncing 并且可以以类似的方式完成。如果是这种情况,请告诉我,我会编辑我的答案。
  • 谢谢,我会调查的。如果有的话,你能提供它的链接吗?顺便说一句,你给出了一个很好的解决方案。
  • 如果您想查看一些代码,我有一个 debounce library on GitHub,但它是用 TypeScript 编写的,并且在这种情况下比您需要的解决方案更复杂,因为我使用 Promise 来尝试保存去抖动函数返回的值。这是一篇在 JavaScript 上下文中解释去抖动概念的文章:JavaScript debounce function
【解决方案3】:

可能是这样的:

let clickedOnce = false;

function alertBtn() {
  if (!clickedOnce) {
    clickedOnce = true;
    setTimeout(alertFunc, 3000);
  }
}

function alertFunc() {
  alert("Alert is clicked so remain alerted");
  clickedOnce = false;
}
<button onclick="alertBtn()">Alert me</button>

【讨论】:

  • 感谢您的回答,但每次点击它仍在执行功能
  • @Rana 现在重试:)
  • 现在它正在工作,但它与其他答案相似(完全)。除了 +1 的回复,您还有其他方法可以解决此问题吗,谢谢。
  • @Rana 是的,我们俩几乎同时想出了这个解决方案。我的版本就是这样,你所要求的,因此更精简:)。感谢您的 +1
【解决方案4】:

最简单的方法是通过setTimeout 简单地控制按钮disabled 的状态。处理程序确实负责执行alertFunc 并在单击时禁用按钮并启动后者的时移活动状态...

function alertFunc() {
  alert("Alert is clicked so remain alerted");
}

function controlButtonAbility(btn) {
  btn.disabled = true;
  setTimeout(() => btn.disabled = false, 5000);
}

function handleButtonClick(evt) {
  const btn = evt.currentTarget;

  controlButtonAbility(btn);

  alertFunc();
}
document
  .querySelector('button')
  .addEventListener('click', handleButtonClick);
<button>Alert me</button>

编辑

“很好的解决方案,感谢响应(+1)。但是警报也可以在 3 秒后执行”

当然……

function alertFunc() {
  alert("Alert is clicked so remain alerted");
}

function controlButtonAbility(btn) {
  btn.disabled = true;
  setTimeout(() => btn.disabled = false, 5000);
}

function handleButtonClick(evt) {
  const btn = evt.currentTarget;

  controlButtonAbility(btn);

  // alertFunc();
  setTimeout(alertFunc, 2000);
}
document
  .querySelector('button')
  .addEventListener('click', handleButtonClick);
<button>Alert me</button>

【讨论】:

  • 很好的解决方案,感谢您的回复(+1)。但是警报也可以在 3 秒后执行吗
猜你喜欢
  • 1970-01-01
  • 2021-01-14
  • 2019-11-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-02-22
  • 1970-01-01
相关资源
最近更新 更多