【问题标题】:Function only being executed with a delay of a keyup event仅在 keyup 事件延迟的情况下执行功能
【发布时间】:2013-08-18 05:09:09
【问题描述】:

编辑:我希望在最后一个 keyup 事件的一秒后调用并执行一个函数。

这是我的代码:http://jsfiddle.net/gKkAQ/

JS:

function aFunction() {
    setTimeout(function () {
        console.log("1");
    }, 1000);
}

$(document).ready(function () {
    $("#Input").keyup(function () {
        aFunction();
    });
});

HTML:

<input type="text" id="Input"></input>

您可以轻松运行 JSFiddle 并在控制台中看到无论您键入多快,该函数都会执行而不管其先前的执行状态(在这种情况下,setTimeout 尚未在 1 秒内完成,但如果您继续输入,所有函数调用都会被执行)

【问题讨论】:

  • 除非函数异步执行某些操作,否则这已经发生了。
  • 如果你描述更多函数内部发生的事情,问题会更清楚。
  • @Sergio 我的代码已添加
  • @TheJinStudio 那么你应该这么说,因为那完全不同:)
  • @MarioRossi 我只能说“哇”。无论如何,谢谢你的回答。

标签: javascript function return call exit


【解决方案1】:

“你会看到函数每秒都在执行。我希望它在最后一个按键操作的一秒后执行”

setTimeout() function 返回一个 id,您可以将其传递给 clearTimeout() 以防止发生超时 - 当然假设您在时间结束之前调用 clearTimeout()

var timeoutId;
function aFunction() {
    clearTimeout(timeoutId);
    timeoutId = setTimeout(function () {
        console.log("1");
    }, 1000);
}

$(document).ready(function () {
    $("#Input").keyup(function () {
        aFunction();
    });
});

使用已经发生的超时 id 调用 clearTimeout() 并没有什么坏处,在这种情况下它没有任何效果。

所以上面的代码清除了之前的超时时间(如果有的话)然后创建一个新的超时时间,效果是console.log()的匿名函数只会在用户停止输入1000ms后执行。如果用户在等待超过 1000 毫秒后再次开始输入,则会再次超时。

【讨论】:

【解决方案2】:

注意:此答案对应于最初的、非常一般的问题,在经过大量编辑和转换为非常具体的问题之前。

这取决于您的确切执行环境。从理论上讲,JavaScript 是单线程的。你描述的情况永远不会发生。然而,在实践中,它确实会发生(尤其是在浏览器内部),并且没有办法完全控制它。

最接近“控制”的替代方法是从检查全局“激活计数器”变量的值开始。如果为 0,则立即递增并继续执行。退出时递减。

为什么这不起作用?因为2次激活可以同时达到测试。由于变量为 0,因此两个测试都将成功,并且都将继续增加变量并执行。与大多数同步/并发问题一样,问题不会系统地发生,而是时不时地随机发生。这使得事情难以检测、重现和纠正。

你可以尝试两次询问变量,如:

if( activationCounter <= 0 ) {
    if( activationCounter <= 0 ) {
        activationCounter++;
        //  Execution
        activationCounter--;
    }
}

在许多圈子中,这被描述为问题的解决方案,但它只会降低冲突的可能性(相当多,但不是为零)。这只是对“双重检查锁定”模式理解不佳的结果。问题仍然会发生,但频率要低得多。我不确定这是好是坏,因为它们将更难以检测、复制和纠正。

【讨论】:

  • 确实,JavaScript 没有线程安全的工具。然而,这可以安全地完成,使用任何操作系统教科书中的 Dijkstra 的 `Cooperating Sequential Processes' 中的技术。我并不是建议您实际实施 Dijkstra 的算法:只是将其用作参考,但要花费大部分精力重新考虑您的方法,这样就不需要进行这样的调整了。
  • Dijkstra 认识到同步原语的需求。如果您没有原语,那么您无能为力(但掷骰子)。最简单的同步原语之一是test and settest and increment。这看起来像if( var++ == 0 )。我们可以说“哦,但是大多数语言都支持”。问题是我们会忘记小写字母:测试和增量必须作为一个单一的、不可分割的、不间断的操作发生。 “快速继任”可能在大多数情况下都有效,但不是真正的解决方案。
  • 嵌套的if 语句是不必要的。 JavaScript 单线程的,不可能同时发生两次执行(修改这个共享变量)。这可能是其他语言的情况,但不适用于此处。除此之外,您的增量/减量(可以改为布尔标志)似乎是原始问题的一个很好的解决方案。
  • @Ian 如果 JavaScript 在所有环境中都是单线程的(实际上不是),那么 no if 将是必要的.没有标志,没有计数器,什么都没有(除非您要防止的是直接或间接递归,但那是完全不同的动物)。
  • @MarioRossi 我认为您误解了 JavaScript 与其他语言的异步行为。是的,JavaScript 在所有浏览器中都是单线程的。它不存在的领域是 Web Workers,它实际上创建新线程以与主线程同时执行,但完全是线程安全的。 JavaScript 中异步事物的工作方式(如setTimoutsetInterval、事件处理程序等)是它们被安排在特定时间执行。当那个时间到来时,当没有其他 JavaScript 执行时,它就会执行。那里没有冲突
猜你喜欢
  • 1970-01-01
  • 2016-11-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-14
  • 1970-01-01
相关资源
最近更新 更多