Heim  >  Artikel  >  Web-Frontend  >  Implementieren von Sleep oder Wait mit JavaScript

Implementieren von Sleep oder Wait mit JavaScript

青灯夜游
青灯夜游nach vorne
2021-01-27 19:14:1211255Durchsuche

Implementieren von Sleep oder Wait mit JavaScript

JavaScript verfügt nicht über eine sleep()-Funktion, die dazu führt, dass der Code eine bestimmte Zeitspanne wartet, bevor er mit der Ausführung fortfährt. Was soll ich tun, wenn JavaScript warten muss? sleep() 函数,该函数会导致代码在恢复执行之前等待指定的时间段。如果需要JavaScript等待,该怎么做呢?

假设您想将三则消息记录到Javascript控制台,每条消息之间要延迟一秒钟。JavaScript中没有 sleep() 方法,所以你可以尝试使用下一个最好的方法 setTimeout()

不幸的是,setTimeout() 不能像你期望的那样正常工作,这取决于你如何使用它。你可能已经在JavaScript循环中的某个点上试过了,看到 setTimeout() 似乎根本不起作用。

问题的产生是由于将 setTimeout() 误解为 sleep() 函数,而实际上它是按照自己的一套规则工作的。

在本文中,我将解释如何使用 setTimeout(),包括如何使用它来制作一个睡眠函数,使JavaScript暂停执行并在连续的代码行之间等待。

浏览一下 setTimeout() 的文档,它似乎需要一个 "延迟 "参数,以毫秒为单位。

回到原始问题,您尝试调用 setTimeout(1000) 在两次调用 console.log() 函数之间等待1秒。

不幸的是 setTimeout() 不能这样工作:

setTimeout(1000)
console.log(1)
setTimeout(1000)
console.log(2)
setTimeout(1000)
console.log(3)

for (let i = 0; i <= 3; i++) {
  setTimeout(1000)
  console.log(`#${i}`)
}

这段代码的结果完全没有延迟,就像 setTimeout() 不存在一样。

回顾文档,你会发现问题在于实际上第一个参数应该是函数调用,而不是延迟。毕竟,setTimeout() 实际上不是 sleep() 方法。

你重写代码以将回调函数作为第一个参数并将必需的延迟作为第二个参数:

setTimeout(() => console.log(1), 1000)
setTimeout(() => console.log(2), 1000)
setTimeout(() => console.log(3), 1000)

for (let i = 0; i <= 3; i++) {
  setTimeout(() => console.log(`#${i}`), 1000)
}

这样一来,三个console.log的日志信息在经过1000ms(1秒)的单次延时后,会一起显示,而不是每次重复调用之间延时1秒的理想效果。

在讨论如何解决此问题之前,让我们更详细地研究一下 setTimeout() 函数。

检查setTimeout ()

你可能已经注意到上面第二个代码片段中使用了箭头函数。这些是必需的,因为你需要将匿名回调函数传递给 setTimeout(),该函数将在超时后运行要执行的代码。

在匿名函数中,你可以指定在超时时间后执行的任意代码:

// 使用箭头语法的匿名回调函数。
setTimeout(() => console.log("你好!"), 1000)
// 这等同于使用function关键字
setTimeout(function() { console.log("你好!") }, 1000)

理论上,你可以只传递函数作为第一个参数,回调函数的参数作为剩余的参数,但对我来说,这似乎从来没有正确的工作:

// 应该能用,但不能用
setTimeout(console.log, 1000, "你好")

人们使用字符串解决此问题,但是不建议这样做。从字符串执行JavaScript具有安全隐患,因为任何不当行为者都可以运行作为字符串注入的任意代码。

// 应该没用,但确实有用
setTimeout(`console.log("你好")`, 1000)

那么,为什么在我们的第一组代码示例中 setTimeout() 失败?好像我们在正确使用它,每次都重复了1000ms的延迟。

原因是 setTimeout() 作为同步代码执行,并且对 setTimeout() 的多次调用均同时运行。每次调用 setTimeout() 都会创建异步代码,该代码将在给定延迟后稍后执行。由于代码段中的每个延迟都是相同的(1000毫秒),因此所有排队的代码将在1秒钟的单个延迟后同时运行。

如前所述,setTimeout() 实际上不是 sleep() 函数,取而代之的是,它只是将异步代码排入队列以供以后执行。幸运的是,可以使用 setTimeout() 在JavaScript中创建自己的 sleep() 函数。

如何编写sleep函数

通过Promises,asyncawait 的功能,您可以编写一个 sleep() 函数,该函数将按预期运行。

但是,你只能从 async 函数中调用此自定义 sleep() 函数,并且需要将其与 await 关键字一起使用。

这段代码演示了如何编写一个 sleep() 函数:

const sleep = (delay) => new Promise((resolve) => setTimeout(resolve, delay))

const repeatedGreetings = async () => {
  await sleep(1000)
  console.log(1)
  await sleep(1000)
  console.log(2)
  await sleep(1000)
  console.log(3)
}
repeatedGreetings()

此JavaScript sleep() 函数的功能与您预期的完全一样,因为 await 导致代码的同步执行暂停,直到Promise被解决为止。

一个简单的选择

另外,你可以在第一次调用 setTimeout() 时指定增加的超时时间。

以下代码等效于上一个示例:

setTimeout(() => console.log(1), 1000)
setTimeout(() => console.log(2), 2000)
setTimeout(() => console.log(3), 3000)

使用增加超时是可行的,因为代码是同时执行的,所以指定的回调函数将在同步代码执行的1、2和3秒后执行。

它会循环运行吗?

如你所料,以上两种暂停JavaScript执行的选项都可以在循环中正常工作。让我们看两个简单的例子。

这是使用自定义 sleep()

Angenommen, Sie möchten drei Nachrichten mit einer Verzögerung von einer Sekunde zwischen den einzelnen Nachrichten in der Javascript-Konsole protokollieren. In JavaScript gibt es keine sleep()-Methode, daher können Sie versuchen, die nächstbeste Methode setTimeout() zu verwenden. 🎜🎜Leider funktioniert setTimeout() nicht so gut, wie Sie es erwarten würden, je nachdem, wie Sie es verwenden. Sie haben dies wahrscheinlich schon einmal in Ihrer JavaScript-Schleife versucht und festgestellt, dass setTimeout() überhaupt nicht zu funktionieren scheint. 🎜🎜Das Problem entsteht durch ein Missverständnis von setTimeout() als Funktion sleep(), obwohl sie tatsächlich nach einem eigenen Regelsatz funktioniert. 🎜🎜In diesem Artikel erkläre ich, wie man setTimeout() verwendet und wie man damit eine Sleep-Funktion erstellt, die bewirkt, dass JavaScript die Ausführung anhält und zwischen aufeinanderfolgenden Codezeilen wartet. 🎜🎜Wenn man sich die Dokumentation für setTimeout() ansieht, scheint es einen „Verzögerungs“-Parameter in Millisekunden zu erfordern. 🎜🎜Zurück zur ursprünglichen Frage: Sie versuchen, setTimeout(1000) aufzurufen, um 1 Sekunde zwischen Aufrufen der Funktion console.log() zu warten. 🎜🎜Leider funktioniert setTimeout() nicht so: 🎜
const sleep = (delay) => new Promise((resolve) => setTimeout(resolve, delay))

async function repeatGreetingsLoop() {
  for (let i = 0; i <= 5; i++) {
      await sleep(1000)
    console.log(`Hello #${i}`)
    }
}
repeatGreetingsLoop()
🎜Das Ergebnis dieses Codes ist überhaupt keine Verzögerung, als ob setTimeout() nicht existieren würde . 🎜🎜Wenn Sie sich die Dokumentation noch einmal ansehen, werden Sie feststellen, dass das Problem darin besteht, dass der erste Parameter eigentlich ein Funktionsaufruf und keine Verzögerung sein sollte. Schließlich ist setTimeout() eigentlich keine sleep()-Methode. 🎜🎜Sie schreiben den Code um, um die Rückruffunktion als ersten Parameter und die erforderliche Verzögerung als zweiten Parameter zu übernehmen: 🎜
for (let i = 0; i <= 5; i++) {
  setTimeout(() => console.log(`Hello #${i}`), 1000 * i)
}
🎜Auf diese Weise werden die Protokollinformationen der drei console.logs nach einzelnen 1000 ms (1 Sekunde) verarbeitet ) Nach der Verzögerung werden sie zusammen angezeigt, anstelle des idealen Effekts einer Verzögerung von 1 Sekunde zwischen jedem wiederholten Aufruf. 🎜🎜Bevor wir diskutieren, wie dieses Problem gelöst werden kann, schauen wir uns die Funktion setTimeout() genauer an. 🎜

Überprüfen Sie setTimeout ()

🎜Möglicherweise ist Ihnen die Verwendung von Pfeilfunktionen im zweiten Codeausschnitt oben aufgefallen. Diese sind erforderlich, da Sie eine anonyme Rückruffunktion an setTimeout() übergeben müssen, die den Code ausführt, der nach dem Timeout ausgeführt werden soll. 🎜🎜In einer anonymen Funktion können Sie beliebigen Code angeben, der nach dem Timeout ausgeführt werden soll: 🎜rrreee🎜Theoretisch könnten Sie einfach die Funktion als ersten Parameter und die Parameter der Callback-Funktion als verbleibende Parameter übergeben, aber für mich: was nie richtig zu funktionieren schien: 🎜rrreee🎜Leute haben dieses Problem mit Strings gelöst, aber das wird nicht empfohlen. Das Ausführen von JavaScript aus einem String hat Auswirkungen auf die Sicherheit, da jeder böswillige Akteur beliebigen Code ausführen kann, der als String eingefügt wird. 🎜rrreee🎜Warum schlägt setTimeout() in unserem ersten Satz Codebeispiele fehl? Es scheint, als würden wir es richtig verwenden, die Verzögerung von 1000 ms wird jedes Mal wiederholt. 🎜🎜Der Grund dafür ist, dass setTimeout() als synchroner Code ausgeführt wird und mehrere Aufrufe von setTimeout() alle gleichzeitig ausgeführt werden. Jeder Aufruf von setTimeout() erstellt asynchronen Code, der später nach einer bestimmten Verzögerung ausgeführt wird. Da jede Verzögerung im Snippet gleich ist (1000 ms), wird der gesamte Code in der Warteschlange nach einer einzelnen Verzögerung von 1 Sekunde gleichzeitig ausgeführt. 🎜🎜Wie bereits erwähnt, ist setTimeout() eigentlich keine sleep()-Funktion, sondern stellt lediglich asynchronen Code für die spätere Ausführung in die Warteschlange. Glücklicherweise können Sie mit setTimeout() Ihre eigene sleep()-Funktion in JavaScript erstellen. 🎜

So schreiben Sie eine Schlaffunktion

🎜Mit den Funktionen von Promises, async und await können Sie eine schreiben sleep()Funktion, die wie erwartet funktioniert. 🎜🎜Allerdings können Sie diese benutzerdefinierte Funktion sleep() nur über die Funktion async aufrufen und müssen sie zusammen mit dem Schlüsselwort await verwenden . 🎜🎜Dieser Code zeigt, wie man eine sleep()-Funktion schreibt: 🎜rrreee🎜Diese JavaScript-sleep()-Funktion funktioniert genau so, wie Sie es erwarten würden, denn await bewirkt, dass die synchrone Ausführung des Codes angehalten wird, bis das Versprechen aufgelöst ist. 🎜<h2 id="item-3">Eine einfache Wahl</h2>🎜Außerdem können Sie beim ersten Aufruf von <code>setTimeout() ein erhöhtes Timeout angeben. 🎜🎜Der folgende Code entspricht dem vorherigen Beispiel: 🎜rrreee🎜Die Verwendung eines erhöhten Timeouts ist möglich, da der Code gleichzeitig ausgeführt wird, sodass die angegebene Rückruffunktion nach 1, 2 und 3 Sekunden der synchronen Codeausführung ausgeführt wird. 🎜

Wird es in einer Schleife laufen?

🎜Wie Sie vielleicht erwarten, funktionieren beide oben genannten Optionen zum Anhalten der JavaScript-Ausführung innerhalb einer Schleife einwandfrei. Schauen wir uns zwei einfache Beispiele an. 🎜🎜Dies ist ein Codeausschnitt, der eine benutzerdefinierte sleep()-Funktion verwendet: 🎜
const sleep = (delay) => new Promise((resolve) => setTimeout(resolve, delay))

async function repeatGreetingsLoop() {
  for (let i = 0; i <= 5; i++) {
      await sleep(1000)
    console.log(`Hello #${i}`)
    }
}
repeatGreetingsLoop()

这是一个简单的使用增加超时的代码片段:

for (let i = 0; i <= 5; i++) {
  setTimeout(() => console.log(`Hello #${i}`), 1000 * i)
}

我更喜欢后一种语法,特别是在循环中使用。

总结

JavaScript可能没有 sleep()wait() 函数,但是使用内置的 setTimeout() 函数很容易创建一个JavaScript,只要你谨慎使用它即可。

就其本身而言,setTimeout() 不能用作 sleep() 函数,但是你可以使用 asyncawait 创建自定义JavaScript sleep() 函数。

采用不同的方法,可以将交错的(增加的)超时传递给 setTimeout() 来模拟 sleep() 函数。之所以可行,是因为所有对setTimeout() 的调用都是同步执行的,就像JavaScript通常一样。

希望这可以帮助你在代码中引入一些延迟——仅使用原始JavaScript,而无需外部库或框架。

祝您编码愉快! 

英文原文地址:https://medium.com/dev-genius/how-to-make-javascript-sleep-or-wait-d95d33c99909

作者:Dr. Derek Austin

更多编程相关知识,请访问:编程视频!!

Das obige ist der detaillierte Inhalt vonImplementieren von Sleep oder Wait mit JavaScript. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:segmentfault.com. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen