From 55ddd4454665a3c66e3d5b186bc79048468d36e7 Mon Sep 17 00:00:00 2001
From: Alexey Pyltsyn Конечно, на практике код выше бесполезен, но в учебных целях он иллюстрирует синтаксис асинхронных функций. Теперь давайте перейдем к реальным примерам. Давайте посмотрим на пример из предыдущей статьи: Вы могли заметить, что мы обернули наш код в функцию и сделали ее асинхронной с помощью acync. Это было обязательно - нам надо создать контейнер, внутри которого будет запускаться асинхронный код и будет возмоность дождаться его результата с помощью await, не блокируя остальной код нашего скрипта. Вы могли заметить, что мы обернули наш код в функцию и сделали ее асинхронной с помощью acync. Это было обязательно - нам надо создать контейнер, внутри которого будет запускаться асинхронный код и будет возможность дождаться его результата с помощью await, не блокируя остальной код нашего скрипта. Внутри Внутри Значение Promise, которое вернет Значение Promise, которое вернет Обратите внимание, когда мы вызываем Как вы помните, асинхронные функции построены поверх promises, поэтому они совместимы со всеми возможностями последних. Мы легко можем подождать выполнение Как вы помните, асинхронные функции построены поверх promises, поэтому они совместимы со всеми возможностями последних. Мы легко можем подождать выполнение Версия с async/await (смотрите live demo и source code), сейчас выглядит так: Асинхронные функции с async/await бывают очень удобными, но есть несколько замечаний, о которых полезно знать. Async/await позволяет вам писать код в синхронном стиле. Ключевое слово Async/await позволяет вам писать код в синхронном стиле. Ключевое слово В каждом примере функция записывает время начала исполнения и сколько времерни понадобилось на испольние В каждом примере функция записывает время начала исполнения и сколько времени понадобилось на исполнение Далее представленна асинхронная функция Далее представлена асинхронная функция В случае с медленным примером Здесь мы просто ждем все три Здесь мы просто ждем все три Во втором В данном случае мы храмим три объекта В данном случае мы храним три объекта Ниже мы ожидаем разрешения промисов из объекта в результат, так как они были запущенны одновременно, блокируя поток, то и разрешатся одновременно. Если вы запустите второй приимер вы увидите alert, сообщающий время выполнения около 3 секунд. Ниже мы ожидаем разрешения промисов из объекта в результат, так как они были запущенны одновременно, блокируя поток, то и разрешатся одновременно. Если вы запустите второй пример вы увидите alert, сообщающий время выполнения около 3 секунд. Важно не забывать о быстродействии применяя await, проверяйте количество блокировок.Переписываем Promises с ипользованием async/await
+Переписываем Promises с использованием async/await
Минуточку, а как это все работает ?
-myFetch()
находится код, который слегка напоминает версию на Promise, но есть важные отличия. Вместо того, чтобы писать цепочку блоков .then()
мы просто использует ключевое слово await
перед вызовом promise-based функции и присваиваем результат в переменную. Ключеовое слово await
говорит JavaScript runtime приостановить код в этой строке, не блокируя остальной код скприта за пределами асинхронной функции. Когда вызов promise-based функции будет готов вернуть результат, выполнение продолжится с этой строки дальше.
+myFetch()
находится код, который слегка напоминает версию на Promise, но есть важные отличия. Вместо того, чтобы писать цепочку блоков .then()
мы просто использует ключевое слово await
перед вызовом promise-based функции и присваиваем результат в переменную. Ключевое слово await
говорит JavaScript runtime приостановить код в этой строке, не блокируя остальной код скрипта за пределами асинхронной функции. Когда вызов promise-based функции будет готов вернуть результат, выполнение продолжится с этой строки дальше.
Пример:let response = await fetch('coffee.jpg');
-fetch()
будет присвоено переменной response
только тогда, когда оно будет доступно - парсер делает паузу на данной строке дожидаясь этого момента. Как только значение доступно, парсер переходит к следующей строке, в которой создается объект Blob
из результата Promise. В этой строке, кстати, также используется await
, потому что метод .blob()
также возвращет Promise. Когда результат готов, мы возвращаем его наружу из myFetch()
.fetch()
будет присвоено переменной response
только тогда, когда оно будет доступно - парсер делает паузу на данной строке дожидаясь этого момента. Как только значение доступно, парсер переходит к следующей строке, в которой создается объект Blob
из результата Promise. В этой строке, кстати, также используется await
, потому что метод .blob()
также возвращает Promise. Когда результат готов, мы возвращаем его наружу из myFetch()
.myFetch()
, она возвращает Promise, поэтому мы можем вызвать .then()
на результате, чтобы отобразить его на экране.
@@ -229,7 +229,7 @@ myFetch().then((blob) => {
Await и Promise.all()
-Promise.all()
, присвоить результат в переменную и все это сделать используя синхронный стиль. Опять, вернемся к примеру, рассмотреному в предыдущей статье. Откройте пример в соседней вкладке, чтобы лучше понять разницу.Promise.all()
, присвоить результат в переменную и все это сделать используя синхронный стиль. Опять, вернемся к примеру, рассмотренному в предыдущей статье. Откройте пример в соседней вкладке, чтобы лучше понять разницу.await
блокирует приостанавливает выполнение ptomise-based функции до того момента, пока promise примет статуc fulfilled. Это не блокирует код за пределами вашей асинхронной функции, тем не менее важно помнить, что внутри асинхронной функции поток выполнения блокируется.
+await
блокирует приостанавливает выполнение ptomise-based функции до того момента, пока promise примет статус fulfilled. Это не блокирует код за пределами вашей асинхронной функции, тем не менее важно помнить, что внутри асинхронной функции поток выполнения блокируется.
Ваш код может стать медленнее за счет большого количества awaited promises, которые идут один за другим. Каждый await
должен дождаться выполнения предыдущего, тогда как на самом деле мы хотим, чтобы наши Promises выполнялись одновременно, как если бы мы не использовали async/await.
@@ -320,7 +320,7 @@ displayContent()
...
}
-timeTest()
промисов, вычитая время в момент запуска функции из времени в момент разрешения обещаний:timeTest()
промисов, вычитая время в момент запуска функции из времени в момент разрешения обещаний:let startTime = Date.now();
timeTest().then(() => {
@@ -329,7 +329,7 @@ timeTest().then(() => {
alert("Time taken in milliseconds: " + timeTaken);
})
-timeTest()
различная для каждого из примеров.timeTest()
различная для каждого из примеров.slow-async-await.html
, timeTest()
выглядит:timeoutPromise()
напрямую, блокируя выполнение на данного блока на 3 секунды прии каждом вызове. Все последующие вызовы вынуждены ждать пока разрешится предыдущий. Если вы запустите первый пример (slow-async-await.html
) вы увидите alert сообщающий время выполнения около 9 секунд. timeoutPromise()
напрямую, блокируя выполнение на данного блока на 3 секунды при каждом вызове. Все последующие вызовы вынуждены ждать пока разрешится предыдущий. Если вы запустите первый пример (slow-async-await.html
) вы увидите alert сообщающий время выполнения около 9 секунд. fast-async-await.html
примере, функция timeTest()
выглядит как:Promise
в переменных, каждый из которых может разрешиться независимо от других.Promise
в переменных, каждый из которых может разрешиться независимо от других.
В качестве последнего замечания, вы можете использовать async
перед методами классов или объектов, вынуждая их возвращать promises. А также await внутри методов объявленных такиим образом. Посмотрите на пример ES class code, который мы наблюдали в статье object-oriented JavaScript, и сравниете его с модифицированной (асинхронной) async
версией ниже:
В качестве последнего замечания, вы можете использовать async
перед методами классов или объектов, вынуждая их возвращать promises. А также await внутри методов объявленных таким образом. Посмотрите на пример ES class code, который мы наблюдали в статье object-oriented JavaScript, и сравните его с модифицированной (асинхронной) async
версией ниже:
class Person { constructor(first, last, age, gender, interests) { diff --git a/files/ru/learn/javascript/asynchronous/concepts/index.html b/files/ru/learn/javascript/asynchronous/concepts/index.html index cd7f119acc..def7da8a78 100644 --- a/files/ru/learn/javascript/asynchronous/concepts/index.html +++ b/files/ru/learn/javascript/asynchronous/concepts/index.html @@ -35,7 +35,7 @@ translation_of: Learn/JavaScript/Asynchronous/Concepts --Такое поведение удручает и говорит о неправильном использовании процессорного времени, к тому же современные компьютеры имеют процессоры с несколькими ядрами. Не нужно ничего ждать, вы можете передать следующую задачу свободному ядру процессора и когда она завершится, то сообщит вам об этом. Такой подход позволяет выполнять разные задачи одновременно, в этом и заключается задача асинхронности в программировании. Программная среда, которую вы используете (браузер в случае веб разработки), должна иметь возможность выполнять различного рода задачи ассинхронно.
+Такое поведение удручает и говорит о неправильном использовании процессорного времени, к тому же современные компьютеры имеют процессоры с несколькими ядрами. Не нужно ничего ждать, вы можете передать следующую задачу свободному ядру процессора и когда она завершится, то сообщит вам об этом. Такой подход позволяет выполнять разные задачи одновременно, в этом и заключается задача асинхронности в программировании. Программная среда, которую вы используете (браузер в случае веб разработки), должна иметь возможность выполнять различного рода задачи асинхронно.
Блокировка кода
@@ -43,7 +43,7 @@ translation_of: Learn/JavaScript/Asynchronous/ConceptsДавайте рассмотрим несколько примеров, которые покажут, что именно значит блокировка.
-В нашем simple-sync.html примере (see it running live), добавим кнопке событие на клик, чтобы при нажатии на нее запускалась трудоемкая операция (рассчет 10000000 дат, и вывод последней рассчитанной даты на консоль) после чего в DOM добавляется еще один параграф:
+В нашем simple-sync.html примере (see it running live), добавим кнопке событие на клик, чтобы при нажатии на нее запускалась трудоемкая операция (расчет 10000000 дат, и вывод последней рассчитанной даты на консоль) после чего в DOM добавляется еще один параграф:
const btn = document.querySelector('button'); btn.addEventListener('click', () => { @@ -106,7 +106,7 @@ alertBtn.addEventListener('click', () =>-Каждая задача будет выполнена последовательно; только когда текущая задача завершится, следующая сможет начаться.
-Как мы говорили выше, большинство компьютеров теперь имеют процессор с несколькими ядрами, т.е. могут выполнять несколько задач одновременно. Языки программирования, поддерживающие многопоточность, могут использовать несколько ядер, чтобы выпонять несколько задач одновременно:
+Как мы говорили выше, большинство компьютеров теперь имеют процессор с несколькими ядрами, т.е. могут выполнять несколько задач одновременно. Языки программирования, поддерживающие многопоточность, могут использовать несколько ядер, чтобы выполнять несколько задач одновременно:
Thread 1: Task A --> Task B Thread 2: Task C --> Task Ddiff --git a/files/ru/learn/javascript/asynchronous/introducing/index.html b/files/ru/learn/javascript/asynchronous/introducing/index.html index 340938e010..7ba34475cf 100644 --- a/files/ru/learn/javascript/asynchronous/introducing/index.html +++ b/files/ru/learn/javascript/asynchronous/introducing/index.html @@ -85,13 +85,13 @@ btn.addEventListener('click', () => { let blob = response.blob(); // display your image blob in the UI somehowЭто проиходит потому что вы не знаете сколько времени займет загрузка картинки, следовательно, когда вы начнёте выполнять вторую строку кода, сгенерируется ошибка (возможно, переодически, возможно, каждый раз), потому что response еще не доступен. Вместо этого, ваш код должен дождаться возвращения response до того, как попытается выполнить дальнешие инструкции.
+Это происходит потому что вы не знаете сколько времени займет загрузка картинки, следовательно, когда вы начнёте выполнять вторую строку кода, сгенерируется ошибка (возможно, периодически, возможно, каждый раз), потому что response еще не доступен. Вместо этого, ваш код должен дождаться возвращения response до того, как попытается выполнить дальнейшие инструкции.
Есть два типа стиля асинхронного кода, с которыми вы столкнетесь в коде JavaScript, старый метод — callbacks (обратные вызовы) и более новый — promise (промисы, обещания). В следующих разделах мы познакомимся с каждым из них.
Асинхронные обратные вызовы
-Асинхронные обратные вызовы — это функции, которые определяются как агрументы при вызове функции, которая начнет выполнение кода на заднем фоне. Когда код на заднем фоне завершает свою работу, он вызвает функцию обратного вызова, оповещающую, что работа сделана, либо оповещающую о трудностях в завершении работы. Обратные вызовы — немного устраревшая практика, но они все еще употребляются в некоторых старомодных, но часто используемых API.
+Асинхронные обратные вызовы — это функции, которые определяются как аргументы при вызове функции, которая начнет выполнение кода на заднем фоне. Когда код на заднем фоне завершает свою работу, он вызывает функцию обратного вызова, оповещающую, что работа сделана, либо оповещающую о трудностях в завершении работы. Обратные вызовы — немного устаревшая практика, но они все еще употребляются в некоторых старомодных, но часто используемых API.
Пример асинхронного обратного вызова вторым параметром {{domxref("EventTarget.addEventListener", "addEventListener()")}} (как мы видели выше):
@@ -105,7 +105,7 @@ let blob = response.blob();Первый параметр — тип прослушиваемого события, второй параметр — функция обратного вызова, вызываемая при срабатывании события.
-При передаче функциии обратного вызова как аргумента в другую функцию, мы передаем только ссылку на функцию как аргумент, следовательно колбэк функция не выполняется мгновенно. Где-то существует "обратный вызов" (отсюда и название), выполняющийся асинхронно внутри тела, содержащего функцию. Эта функция должна выполнять функцию обратного вызова в нужный момент.
+При передаче функции обратного вызова как аргумента в другую функцию, мы передаем только ссылку на функцию как аргумент, следовательно колбэк функция не выполняется мгновенно. Где-то существует "обратный вызов" (отсюда и название), выполняющийся асинхронно внутри тела, содержащего функцию. Эта функция должна выполнять функцию обратного вызова в нужный момент.
Вы можете написать свою собственную функцию, содержащую функцию обратного вызова. Давайте взглянем на еще один пример, в котором происходит загрузка ресурсов через
@@ -131,11 +131,11 @@ function displayImage(blob) { loadAsset('coffee.jpg', 'blob', displayImage);XMLHttpRequest
API (запустите пример, и посмотрите исходный код):
Мы создали функцию displayImage()
, которая представляет blob, переданный в нее, как обьект URL, и создает картинку, в которой отображается URL, добавляя ее в элемент документа <body>
. Однако, далее мы создаем функцию loadAsset()
, которая принимает функцию обратного вызова в качестве параметра, вместе с URL для получения данных и типом контента. Для получения данных из URL используется XMLHttpRequest
(часто сокращается до аббревиатуры "XHR") , перед тем как передать ответ в функцию обратного вызова для дальнейшей обработки. В этом случае функция обратного вызова ждет, пока XHR закончит загрузку данных (используя обрабочик события onload
) перед отправкой данных в функцию обратного вызова.
Мы создали функцию displayImage()
, которая представляет blob, переданный в нее, как объект URL, и создает картинку, в которой отображается URL, добавляя ее в элемент документа <body>
. Однако, далее мы создаем функцию loadAsset()
, которая принимает функцию обратного вызова в качестве параметра, вместе с URL для получения данных и типом контента. Для получения данных из URL используется XMLHttpRequest
(часто сокращается до аббревиатуры "XHR") , перед тем как передать ответ в функцию обратного вызова для дальнейшей обработки. В этом случае функция обратного вызова ждет, пока XHR закончит загрузку данных (используя обработчик события onload
) перед отправкой данных в функцию обратного вызова.
Функции обратного вызова универсальны — они не только позволяют вам контролировать порядок, в котором запускаются функции и данные, передающиеся между ними, они также позволяют передавать данные различным функциям, в зависимости от обстоятельств. Вы можете выполнять различные действия с загруженным ответом, такие как processJSON()
, displayText()
, и другие.
Заметьте, что не все функции обратного вызова асинхронны — некторые запускаются синхронно. Например, при использовании {{jsxref("Array.prototype.forEach()")}} для перебора элементов массива (запустите пример, и посмотрите исходный код):
+Заметьте, что не все функции обратного вызова асинхронны — некоторые запускаются синхронно. Например, при использовании {{jsxref("Array.prototype.forEach()")}} для перебора элементов массива (запустите пример, и посмотрите исходный код):
const gods = ['Apollo', 'Artemis', 'Ares', 'Zeus']; @@ -162,12 +162,12 @@ gods.forEach(function (eachName, index){Заметка: Вы можете посмотреть законченную версию на github (посмотрите исходный код и запустите пример).
-В примере видно, как
+fetch()
принимает один параметр — URL ресурса, который нужно получить из сети, — и возвращает промис. Промис или обещание — это объект, представляющий асинхронную операцию, выполенную удачно или неудачно. Он представляет собой как бы промежуточное состояние. По сути, это способ браузера сказать: "я обещаю вернуться к вам с ответом как можно скорее," отсюда и название "обещание."В примере видно, как
-fetch()
принимает один параметр — URL ресурса, который нужно получить из сети, — и возвращает промис. Промис или обещание — это объект, представляющий асинхронную операцию, выполненную удачно или неудачно. Он представляет собой как бы промежуточное состояние. По сути, это способ браузера сказать: "я обещаю вернуться к вам с ответом как можно скорее," отсюда и название "обещание."Может пнадобиться много времени, чтобы привыкнуть к данной концепуии; это немного напоминает {{interwiki("wikipedia", "Кот Шрёдингера")}} в действии. Ни один из возможных результатов еще не произошел, поэтому операция fetch в настоящее время ожидает результата. Далее у нас есть три блока кода следующих сразу после
+fetch()
:Может понадобиться много времени, чтобы привыкнуть к данной концепции; это немного напоминает {{interwiki("wikipedia", "Кот Шрёдингера")}} в действии. Ни один из возможных результатов еще не произошел, поэтому операция fetch в настоящее время ожидает результата. Далее у нас есть три блока кода следующих сразу после
fetch()
:
then()
блока. Оба включают в себя функцию обратного, которая запустится, если предыдущая операция закончилась успешно, и каждая функция обратного вызова принимает на вход результат предыдущей успешно выполненной операции, таким образом вы можете выполнять операции последовательно. Каждый .then()
блок возвращает новый promise, это значит что вы можете объеденять в цепочки (чейнить) блоки .then()
, таким образом можно выполнить несколько асинхронных операций по порядку, одну за другой.then()
блока. Оба включают в себя функцию обратного, которая запустится, если предыдущая операция закончилась успешно, и каждая функция обратного вызова принимает на вход результат предыдущей успешно выполненной операции, таким образом вы можете выполнять операции последовательно. Каждый .then()
блок возвращает новый promise, это значит что вы можете объединять в цепочки (чейнить) блоки .then()
, таким образом можно выполнить несколько асинхронных операций по порядку, одну за другой.catch()
блок описывается в конце и будет запущен если какой-либо .then()
блок завершится с ошибкой — это аналогично синхронному try...catch
, ошибка становится доступной внутри catch()
, что может быть использовано для сообщения пользователю о типе возникшей ошибки. Однако синхронный try...catch
не будет работать с promise, хотя будет работать с async/await, с которыми вы познакомитесь позже.Давайте рассмотрим пример, который дополнительно иллюстрирует природу асинхронного кода, показывая, что может произойти, когда мы не полностью осознаем порядок выполнения кода, и проблемы, связанные с попыткой трактовать асинхронный код как синхронный. Следующий пример довольно похож на тот, что мы видели раньше (запустите пример, и посмотрте исходный код). Одно из отличий состоит в том, что мы включили ряд операторов {{domxref("console.log()")}} чтобы проиллюстрировать порядок, в котором, как вы думаете, будет выполняться код.
+Давайте рассмотрим пример, который дополнительно иллюстрирует природу асинхронного кода, показывая, что может произойти, когда мы не полностью осознаем порядок выполнения кода, и проблемы, связанные с попыткой трактовать асинхронный код как синхронный. Следующий пример довольно похож на тот, что мы видели раньше (запустите пример, и посмотреть исходный код). Одно из отличий состоит в том, что мы включили ряд операторов {{domxref("console.log()")}} чтобы проиллюстрировать порядок, в котором, как вы думаете, будет выполняться код.
console.log ('Starting'); let image; @@ -255,7 +255,7 @@ console.log("all done");
Чтобы исправить проблемный пример с fetch()
и заставить все три сообщения console.log()
появиться в желаемом порядке, вы можете также запустить третье сообщение console.log()
асинхронно. Этого можно добиться, переместив его внутрь другого блока .then()
присоединенного к концу второго, или просто переместив его внутрь второго блока then()
. Попробуйте иправить это сейчас..
Чтобы исправить проблемный пример с fetch()
и заставить все три сообщения console.log()
появиться в желаемом порядке, вы можете также запустить третье сообщение console.log()
асинхронно. Этого можно добиться, переместив его внутрь другого блока .then()
присоединенного к концу второго, или просто переместив его внутрь второго блока then()
. Попробуйте исправить это сейчас..
Заметка: Если вы застряли, вы можете найти ответ здесь (также можно посмотреть запущенный пример). Также вы можете найти много информации о промисах в нашем гайде Основные понятия асинхронного программирования позднее в этом модуле.
diff --git a/files/ru/learn/javascript/asynchronous/timeouts_and_intervals/index.html b/files/ru/learn/javascript/asynchronous/timeouts_and_intervals/index.html index 3edcaf64c8..7cd498d9a7 100644 --- a/files/ru/learn/javascript/asynchronous/timeouts_and_intervals/index.html +++ b/files/ru/learn/javascript/asynchronous/timeouts_and_intervals/index.html @@ -1,5 +1,5 @@ --- -title: 'Объединенный асинхронный JavaScript: Таймайты и интервалы' +title: 'Объединенный асинхронный JavaScript: Таймауты и интервалы' slug: Learn/JavaScript/Asynchronous/Timeouts_and_intervals translation_of: Learn/JavaScript/Asynchronous/Timeouts_and_intervals original_slug: Learn/JavaScript/Asynchronous/Таймауты_и_интервалы @@ -35,7 +35,7 @@ original_slug: Learn/JavaScript/Asynchronous/Таймауты_и_интерваsetInterval()
requestAnimationFrame()
Асинхронный код, установленный этими функциями, выполняется в основном потоке (по истечении указанного им таймера).
@@ -176,7 +176,7 @@ clearInterval(myInterval);При работе с setTimeout ()
и setInterval ()
следует помнить о нескольких вещах. Давайте рассмотрим их.
Есть еще один способ использования setTimeout ()
: вы можете вызвать его рекурсивно для повторного запуска одного и того же кода вместо использования setInterval ()
.
Идея состоит в том, чтобы определить функцию, в которой ваша анимация обновляется (например, ваши спрайты перемещаются, счет обновляется, данные обновляются или что-то еще). Затем вы вызываете его, чтобы начать процесс. В конце функционального блока вы вызываете requestAnimationFrame ()
со ссылкой на функцию, переданной в качестве параметра, и это дает браузеру указание вызвать функцию снова при следующей перерисовке дисплея. Затем он выполняется непрерывно, поскольку код рекурсивно вызывает requestAnimationFrame ().
Note: Если вы хотите выполнить простое постоянное анимирование DOM , CSS Анимация вероятно будет быстрее. Она высисляется непосредственно внутренним кодом браузера, а не JavaScript.
+Note: Если вы хотите выполнить простое постоянное анимирование DOM , CSS Анимация вероятно будет быстрее. Она вычисляется непосредственно внутренним кодом браузера, а не JavaScript.
Однако, если вы делаете что-то более сложное, включающее объекты, которые не доступны напрямую в the DOM (такие как 2D Canvas API или WebGL ), requestAnimationFrame()
предпочтительный вариант в большинстве случаев.
Плавность анимации напрямую зависит от частоты кадров анимации и измеряется в кадрах в секунду (fps). Чем выше это число, тем плавнее будет выглядеть ваша анимация до точки.
+Плавность анимации напрямую зависит от частоты кадров анимации и измеряется в кадрах в секунду (fps). Чем выше это число, тем плавное будет выглядеть ваша анимация до точки.
Поскольку большинство экранов имеют частоту обновления 60 Гц, максимальная частота кадров, к которой вы можете стремиться, составляет 60 кадров в секунду (FPS) при работе с веб-браузерами. Однако большее количество кадров означает больше обработки, которая часто может вызывать заикание и пропуски, также известные как пропадание кадров или заедание.
@@ -317,7 +317,7 @@ draw();requestAnimationFrame ()
поддерживается в более поздних версиях браузеров, чем setInterval ()
/ setTimeout ()
. Интересно, что он доступен в Internet Explorer 10 и выше.
Итак, если вам не тербуется поддержка старых версий IE, нет особых причин не использовать requestAnimationFrame()
.
Итак, если вам не требуется поддержка старых версий IE, нет особых причин не использовать requestAnimationFrame()
.
Возьмите базовый HTML шаблон (такой как этот).
Поместите пустой {{htmlelement("div")}} елемент внутри элемента {{htmlelement("body")}}, затем добавьте внутрь символ ↻ . Этот символ будет действовать как spinner в нашем примере.
+Поместите пустой {{htmlelement("div")}} элемент внутри элемента {{htmlelement("body")}}, затем добавьте внутрь символ ↻ . Этот символ будет действовать как spinner в нашем примере.
Применитеpply следующий CSS к HTML шаблону (любым предпочитаемым способом). Он установ красный фон на странице, высоту <body>
равную 100%
высоты {{htmlelement("html")}} , и центрирует <div>
внутри <body>
, по горизонтали и вертикали.
Разместите {{htmlelement("script")}} элемент перед </body>
.
Разместите следующий JavaScript код в <script>
. Здесь вы сохраняете ссылку на <div>
внутри, устанавливаете дяпеременной rotateCount
значение 0
, устанавливаете неинициализированную переменную, которая позже будет использоваться для хранения ссылки на вызов requestAnimationFrame()
, и устанавливаете для переменной startTime
значение null
, которая будет позже использоваться для хранения времени начала requestAnimationFrame()
.
Разместите следующий JavaScript код в <script>
. Здесь вы сохраняете ссылку на <div>
внутри, устанавливаете для переменной rotateCount
значение 0
, устанавливаете неинициализированную переменную, которая позже будет использоваться для хранения ссылки на вызов requestAnimationFrame()
, и устанавливаете для переменной startTime
значение null
, которая будет позже использоваться для хранения времени начала requestAnimationFrame()
.
const spinner = document.querySelector('div'); let rotateCount = 0; @@ -369,7 +369,7 @@ let rAF;
Под предыдущим кодом вставьте функцию draw()
соторая будет использоваться для хранения нашешо кода анимации, который включает параметр timestamp
:
Под предыдущим кодом вставьте функцию draw()
которая будет использоваться для хранения нашего кода анимации, который включает параметр timestamp
:
function draw(timestamp) { @@ -411,7 +411,7 @@ let rAF;Note: Вы можете посмотреть рабочий образец на GitHub. ( исходный код.)
Очистить вызов requestAnimationFrame ()
можно, вызвав соответствующий метод cancelAnimationFrame ()
. (Обратите внимание, что имя функции начинается с «cancel», а не «clear», как у методов «set ...».)
requestAnimationFrame()
Одним из ограничений requestAnimationFrame ()
является то, что вы не можете выбирать частоту кадров. В большинстве случаев это не проблема, так как обычно вы хотите, чтобы ваша анимация работала как можно плавнее. Но как насчет того, чтобы создать олдскульную 8-битную анимацию?
Одним из ограничений requestAnimationFrame ()
является то, что вы не можете выбирать частоту кадров. В большинстве случаев это не проблема, так как обычно вы хотите, чтобы ваша анимация работала как можно плавное. Но как насчет того, чтобы создать олдскульную 8-битную анимацию?
Это было проблемой, например в анимации ходьбы, вдохновленной островом обезьян, из статьи Drawing Graphics:
@@ -483,7 +483,7 @@ let rAF;Прежде всего, скачайте стартовый файл. Он содержит законченную структуру HTML и стили CSS, что дает нам игровую доску, которая показывает информацию двух игроков (как показано выше), но с счетчиком и параграфом результатов, отображаемыми друг над другом. Вам нужно просто написать JavaScript код.
Внутри пустого элемента {{htmlelement("script")}} на вашей старнице, начните с добавления следующих строк кода, котороые определяют некотороые переменные и константы, которые вам понадобятся в дальнейшем:
+Внутри пустого элемента {{htmlelement("script")}} на вашей странице, начните с добавления следующих строк кода, которые определяют некоторые переменные и константы, которые вам понадобятся в дальнейшем:
const spinner = document.querySelector('.spinner p'); const spinnerContainer = document.querySelector('.spinner'); @@ -500,7 +500,7 @@ const result = document.querySelector('.result');
Note: Вы увидете, что этот пример вызывает setTimeout()
без сохранения возвращаемого значения. (не let myTimeout = setTimeout(functionName, interval)
.)
Note: Вы увидите, что этот пример вызывает setTimeout()
без сохранения возвращаемого значения. (не let myTimeout = setTimeout(functionName, interval)
.)
Это прекрасно работает, если вам не нужно очищать интервал / тайм-аут в любой момент. Если вы это сделаете, вам нужно будет сохранить возвращенный идентификатор!
keydown
. При нажатии любой кнопки запускается функция keyHandler()
.keyHandler()
, код включает обьект события в качестве параметра (представленного e
) — его свойство {{domxref("KeyboardEvent.key", "key")}} содержит только что нажатую клавишу, и вы можете использовать это для твета на определенные нажатия клавиш определенными действиями.isOver
значение false, чтобы мы могли отслеживать, были ли нажаты правильные клавиши, чтобы игрок 1 или 2 выиграл. Мы не хотим, чтобы игра заканчивалась при нажатии неправильной клваиши.keyHandler()
, код включает объект события в качестве параметра (представленного e
) — его свойство {{domxref("KeyboardEvent.key", "key")}} содержит только что нажатую клавишу, и вы можете использовать это для ответа на определенные нажатия клавиш определенными действиями.isOver
значение false, чтобы мы могли отслеживать, были ли нажаты правильные клавиши, чтобы игрок 1 или 2 выиграл. Мы не хотим, чтобы игра заканчивалась при нажатии неправильной клавиши.e.key
в консоли, это полезный способ узнать значение различных клавиш, которые вы нажимаете.e.key
принимает значение "a", отобразить сообщение о том, что Player 1 выиграл, а когда e.key
это "l", отобразить сообщение о том, что Player 2 выиграл. (Note: Это будет работать только со строчными буквами a и l — если переданы прописные A или L , это считается другими клавишами!) Если была нажата одна из этих клавиш, установите для isOver
значение true
.isOver
равно true
, удалите прослушиватель событий keydown
с помощью {{domxref("EventTarget.removeEventListener", "removeEventListener()")}} чтобы после того, как произошло выигрышное нажатие, больше не было возможности ввода с клавиатуры, чтобы испортить финальный результат игры. Вы также используете setTimeout()
для вызова reset()
через 5 секунд — как обьяснялось ранее, эта функция сбрасывает игру обратно в исходное состояние, чтобы можно было начать новую игру.isOver
равно true
, удалите прослушиватель событий keydown
с помощью {{domxref("EventTarget.removeEventListener", "removeEventListener()")}} чтобы после того, как произошло выигрышное нажатие, больше не было возможности ввода с клавиатуры, чтобы испортить финальный результат игры. Вы также используете setTimeout()
для вызова reset()
через 5 секунд — как объяснялось ранее, эта функция сбрасывает игру обратно в исходное состояние, чтобы можно было начать новую игру.