Источник: Официальный аккаунт «Full Stack Developer»
JavaScript не имеетsleep()
Функция, которая заставляет код ждать указанный период времени, прежде чем возобновить выполнение. Что делать, если вам нужен JavaScript для ожидания?
Допустим, вы хотите записать три сообщения в консоль Javascript с задержкой в одну секунду между каждым сообщением. Нет в JavaScriptsleep()
метод, так что вы можете попробовать использовать следующий лучший метод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.logs будет отображаться вместе после одной задержки в 1000 мс (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()
потерпеть неудачу? Похоже, мы используем его правильно, каждый раз повторяя задержку в 1000 мс.
Причина в том,setTimeout()
выполняться как синхронный код иsetTimeout()
Несколько вызовов выполняются одновременно. каждый звонокsetTimeout()
создаст асинхронный код, который будет выполняться позже, после заданной задержки. Поскольку каждая задержка во фрагменте одинакова (1000 мс), все коды в очереди будут выполняться одновременно после одной задержки в 1 секунду.
Как упоминалось ранее,setTimeout()
не совсемsleep()
вместо этого он просто ставит в очередь асинхронный код для последующего выполнения. К счастью, можно использоватьsetTimeout()
Создайте свой собственный в JavaScriptsleep()
функция.
Как написать функцию сна
Через обещания,async
а такжеawait
функцию, вы можете написать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()
этот javascriptsleep()
Функция работает именно так, как вы ожидаете, потому чтоawait
Заставляет синхронное выполнение кода приостанавливаться до тех пор, пока обещание не будет разрешено.
легкий выбор
Кроме того, вы можете позвонитьsetTimeout()
При указании увеличенного таймаута.
Следующий код эквивалентен предыдущему примеру:
setTimeout(() => console.log(1), 1000)
setTimeout(() => console.log(2), 2000)
setTimeout(() => console.log(3), 3000)
Использование увеличенного времени ожидания работает, потому что код выполняется одновременно, поэтому указанная функция обратного вызова будет выполняться через 1, 2 и 3 секунды после выполнения синхронного кода.
Будет ли он работать в цикле?
Как и следовало ожидать, оба вышеуказанных варианта приостановки выполнения JavaScript прекрасно работают в цикле. Давайте рассмотрим два простых примера.
Это использование пользовательскогоsleep()
Фрагмент кода для функции:
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()
функция, но вы можете использоватьasync
а такжеawait
Создать собственный JavaScriptsleep()
функция.
Используя другой подход, поэтапный (увеличивающийся) тайм-аут может быть передан вsetTimeout()
имитироватьsleep()
функция. Это возможно, потому что всеsetTimeout()
Вызовы выполняются синхронно, как это обычно делает JavaScript.
Надеюсь, это поможет вам ввести некоторую задержку в свой код — просто используя необработанный JavaScript, никаких внешних библиотек или фреймворков не требуется.
Удачного кодирования! 👍💻🔥😊🖖