From 55ddd4454665a3c66e3d5b186bc79048468d36e7 Mon Sep 17 00:00:00 2001 From: Alexey Pyltsyn Date: Mon, 15 Mar 2021 14:29:50 +0300 Subject: Auto fixes --- .../javascript/asynchronous/async_await/index.html | 24 +++++++-------- .../javascript/asynchronous/concepts/index.html | 6 ++-- .../javascript/asynchronous/introducing/index.html | 20 ++++++------ .../asynchronous/timeouts_and_intervals/index.html | 36 +++++++++++----------- 4 files changed, 43 insertions(+), 43 deletions(-) (limited to 'files/ru/learn/javascript/asynchronous') diff --git a/files/ru/learn/javascript/asynchronous/async_await/index.html b/files/ru/learn/javascript/asynchronous/async_await/index.html index 8146dcfaa1..bef0f49847 100644 --- a/files/ru/learn/javascript/asynchronous/async_await/index.html +++ b/files/ru/learn/javascript/asynchronous/async_await/index.html @@ -86,7 +86,7 @@ hello().then(alert);

Конечно, на практике код выше бесполезен, но в учебных целях он иллюстрирует синтаксис асинхронных функций. Теперь давайте перейдем к реальным примерам.

-

Переписываем Promises с ипользованием async/await

+

Переписываем Promises с использованием async/await

Давайте посмотрим на пример из предыдущей статьи:

@@ -154,15 +154,15 @@ myFetch().then((blob) => {

Минуточку, а как это все работает ?

-

Вы могли заметить, что мы обернули наш код в функцию и сделали ее асинхронной с помощью acync. Это было обязательно - нам надо создать контейнер, внутри которого будет запускаться асинхронный код и будет возмоность дождаться его результата с помощью await, не блокируя остальной код нашего скрипта.

+

Вы могли заметить, что мы обернули наш код в функцию и сделали ее асинхронной с помощью acync. Это было обязательно - нам надо создать контейнер, внутри которого будет запускаться асинхронный код и будет возможность дождаться его результата с помощью 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');
-

Значение Promise, которое вернет fetch() будет присвоено переменной response только тогда, когда оно будет доступно - парсер делает паузу на данной строке дожидаясь этого момента. Как только значение доступно, парсер переходит к следующей строке, в которой создается объект Blob из результата Promise. В этой строке, кстати, также используется await, потому что метод .blob() также возвращет Promise. Когда результат готов, мы возвращаем его наружу из myFetch().

+

Значение Promise, которое вернет fetch() будет присвоено переменной response только тогда, когда оно будет доступно - парсер делает паузу на данной строке дожидаясь этого момента. Как только значение доступно, парсер переходит к следующей строке, в которой создается объект Blob из результата Promise. В этой строке, кстати, также используется await, потому что метод .blob() также возвращает Promise. Когда результат готов, мы возвращаем его наружу из myFetch().

Обратите внимание, когда мы вызываем myFetch(), она возвращает Promise, поэтому мы можем вызвать .then() на результате, чтобы отобразить его на экране.

@@ -229,7 +229,7 @@ myFetch().then((blob) => {

Await и Promise.all()

-

Как вы помните, асинхронные функции построены поверх promises, поэтому они совместимы со всеми возможностями последних. Мы легко можем подождать выполнение Promise.all(), присвоить результат в переменную и все это сделать используя синхронный стиль. Опять, вернемся к примеру, рассмотреному в предыдущей статье. Откройте пример в соседней вкладке, чтобы лучше понять разницу.

+

Как вы помните, асинхронные функции построены поверх promises, поэтому они совместимы со всеми возможностями последних. Мы легко можем подождать выполнение Promise.all(), присвоить результат в переменную и все это сделать используя синхронный стиль. Опять, вернемся к примеру, рассмотренному в предыдущей статье. Откройте пример в соседней вкладке, чтобы лучше понять разницу.

Версия с async/await (смотрите live demo и source code), сейчас выглядит так:

@@ -298,7 +298,7 @@ displayContent()

Асинхронные функции с async/await бывают очень удобными, но есть несколько замечаний, о которых полезно знать.

-

Async/await позволяет вам писать код в синхронном стиле. Ключевое слово await блокирует приостанавливает выполнение ptomise-based функции до того момента, пока promise примет статуc fulfilled. Это не блокирует код за пределами вашей асинхронной функции, тем не менее важно помнить, что внутри асинхронной функции поток выполнения блокируется.
+

Async/await позволяет вам писать код в синхронном стиле. Ключевое слово 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() выглядит:

@@ -339,7 +339,7 @@ timeTest().then(() => { await timeoutPromise(3000); } -

Здесь мы просто ждем все три  timeoutPromise() напрямую, блокируя выполнение на данного блока на 3 секунды прии каждом вызове. Все последующие вызовы вынуждены ждать пока разрешится предыдущий. Если вы запустите первый пример (slow-async-await.html) вы увидите alert сообщающий время выполнения около 9 секунд. 

+

Здесь мы просто ждем все три  timeoutPromise() напрямую, блокируя выполнение на данного блока на 3 секунды при каждом вызове. Все последующие вызовы вынуждены ждать пока разрешится предыдущий. Если вы запустите первый пример (slow-async-await.html) вы увидите alert сообщающий время выполнения около 9 секунд. 

Во втором  fast-async-await.html примере, функция timeTest() выглядит как:

@@ -353,9 +353,9 @@ timeTest().then(() => { await timeoutPromise3; } -

В данном случае мы храмим три объекта Promise в переменных,  каждый из которых может разрешиться независимо от других.

+

В данном случае мы храним три объекта Promise в переменных,  каждый из которых может разрешиться независимо от других.

-

Ниже мы ожидаем разрешения промисов из объекта в результат, так как они были запущенны одновременно, блокируя поток, то и разрешатся одновременно. Если вы запустите второй приимер вы увидите alert, сообщающий время выполнения около 3 секунд.

+

Ниже мы ожидаем разрешения промисов из объекта в результат, так как они были запущенны одновременно, блокируя поток, то и разрешатся одновременно. Если вы запустите второй пример вы увидите alert, сообщающий время выполнения около 3 секунд.

Важно не забывать о быстродействии применяя await, проверяйте количество блокировок.

@@ -363,7 +363,7 @@ timeTest().then(() => {

Async/await class methods

-

В качестве последнего замечания, вы можете использовать  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
 
 

Multi-colored macOS beachball busy spinner

-

Такое поведение удручает и говорит о неправильном использовании процессорного времени, к тому же современные компьютеры имеют процессоры с несколькими ядрами. Не нужно ничего ждать, вы можете передать следующую задачу свободному ядру процессора и когда она завершится, то сообщит вам об этом. Такой подход позволяет выполнять разные задачи одновременно, в этом и заключается задача асинхронности в программировании. Программная среда, которую вы используете (браузер в случае веб разработки), должна иметь возможность выполнять различного рода задачи ассинхронно.

+

Такое поведение удручает и говорит о неправильном использовании процессорного времени, к тому же современные компьютеры имеют процессоры с несколькими ядрами. Не нужно ничего ждать, вы можете передать следующую задачу свободному ядру процессора и когда она завершится, то сообщит вам об этом. Такой подход позволяет выполнять разные задачи одновременно, в этом и заключается задача асинхронности в программировании. Программная среда, которую вы используете (браузер в случае веб разработки), должна иметь возможность выполнять различного рода задачи асинхронно.

Блокировка кода

@@ -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 D
diff --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();

Первый параметр — тип прослушиваемого события, второй параметр — функция обратного вызова, вызываемая при срабатывании события.

-

При передаче функциии обратного вызова как аргумента в другую функцию, мы передаем только ссылку на функцию как аргумент, следовательно колбэк функция не выполняется мгновенно. Где-то существует "обратный вызов" (отсюда и название), выполняющийся асинхронно внутри тела, содержащего функцию. Эта функция должна выполнять функцию обратного вызова в нужный момент.

+

При передаче функции обратного вызова как аргумента в другую функцию, мы передаем только ссылку на функцию как аргумент, следовательно колбэк функция не выполняется мгновенно. Где-то существует "обратный вызов" (отсюда и название), выполняющийся асинхронно внутри тела, содержащего функцию. Эта функция должна выполнять функцию обратного вызова в нужный момент.

Вы можете написать свою собственную функцию, содержащую функцию обратного вызова. Давайте взглянем на еще один пример, в котором происходит загрузка ресурсов через XMLHttpRequest API (запустите пример, и посмотрите исходный код):

@@ -131,11 +131,11 @@ function displayImage(blob) { loadAsset('coffee.jpg', 'blob', displayImage);
-

Мы создали  функцию 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():

@@ -194,7 +194,7 @@ gods.forEach(function (eachName, index){

Природа асинхронного кода

-

Давайте рассмотрим пример, который дополнительно иллюстрирует природу асинхронного кода, показывая, что может произойти, когда мы не полностью осознаем порядок выполнения кода, и проблемы, связанные с попыткой трактовать асинхронный код как синхронный. Следующий пример довольно похож на тот, что мы видели раньше (запустите пример, и посмотрте исходный код). Одно из отличий состоит в том, что мы включили ряд операторов {{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()
-
Современная версия setInterval (). Выполняут указанный блок кода перед тем, как браузер в следующий раз перерисовывает отображение, позволяя запускать анимацию с подходящей частотой кадров независимо от среды, в которой она выполняется.
+
Современная версия setInterval (). Выполняют указанный блок кода перед тем, как браузер в следующий раз перерисовывает отображение, позволяя запускать анимацию с подходящей частотой кадров независимо от среды, в которой она выполняется.

Асинхронный код, установленный этими функциями, выполняется в основном потоке (по истечении указанного им таймера).

@@ -176,7 +176,7 @@ clearInterval(myInterval);

При работе с setTimeout () и setInterval () следует помнить о нескольких вещах. Давайте рассмотрим их.

-

Рекурсивые таймауты

+

Рекурсивные таймауты

Есть еще один способ использования setTimeout (): вы можете вызвать его рекурсивно для повторного запуска одного и того же кода вместо использования setInterval ().

@@ -253,14 +253,14 @@ draw();

Идея состоит в том, чтобы определить функцию, в которой ваша анимация обновляется (например, ваши спрайты перемещаются, счет обновляется, данные обновляются или что-то еще). Затем вы вызываете его, чтобы начать процесс. В конце функционального блока вы вызываете 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().

Простой пример

@@ -332,7 +332,7 @@ draw();

Возьмите базовый HTML шаблон (такой как этот).

  • -

    Поместите пустой  {{htmlelement("div")}} елемент внутри элемента {{htmlelement("body")}}, затем добавьте внутрь символ ↻ . Этот символ будет действовать как spinner в нашем примере.

    +

    Поместите пустой  {{htmlelement("div")}} элемент внутри элемента {{htmlelement("body")}}, затем добавьте внутрь символ ↻ . Этот символ будет действовать как spinner в нашем примере.

  • Применитеpply следующий CSS к HTML шаблону (любым предпочитаемым способом). Он установ красный фон на странице, высоту <body> равную 100% высоты {{htmlelement("html")}} , и центрирует <div> внутри <body>, по горизонтали и вертикали.

    @@ -360,7 +360,7 @@ div {

    Разместите  {{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. ( исходный код.)

    -

    Очbстка вызова  requestAnimationFrame() 

    +

    Очистка вызова  requestAnimationFrame() 

    Очистить вызов requestAnimationFrame () можно, вызвав соответствующий метод cancelAnimationFrame (). (Обратите внимание, что имя функции начинается с «cancel», а не «clear», как у методов «set ...».)

    @@ -436,7 +436,7 @@ let rAF;

    Регулировка анимации 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');
  • Ссылка на элемент {{htmlelement("div")}} содержащий спиннер, используемый для отображения и скрытия.
  • Счетчик поворотов. Он определяет, на сколько вы хотите показывать вращение спиннера на каждом кадре анимации.
  • Нулевое время начала. Это будет заполнено временем начала, когда счетчик начнет вращаться.
  • -
  • Неинициализировання переменная для последующего хранения вызова {{domxref("Window.requestAnimationFrame", "requestAnimationFrame()")}} который анимирует спиннер.
  • +
  • Неинициализированная переменная для последующего хранения вызова {{domxref("Window.requestAnimationFrame", "requestAnimationFrame()")}} который анимирует спиннер.
  • Ссылка на кнопку Start .
  • Ссылка на параграф результатов.
  • @@ -559,7 +559,7 @@ function start() { }
    -

    Note: Вы увидете, что этот пример вызывает setTimeout() без сохранения возвращаемого значения. (не  let myTimeout = setTimeout(functionName, interval).) 

    +

    Note: Вы увидите, что этот пример вызывает setTimeout() без сохранения возвращаемого значения. (не  let myTimeout = setTimeout(functionName, interval).) 

    Это прекрасно работает, если вам не нужно очищать интервал / тайм-аут в любой момент. Если вы это сделаете, вам нужно будет сохранить возвращенный идентификатор!

    @@ -602,11 +602,11 @@ function start() {
  • Во-первых, отмените анимацию спиннера с помощью {{domxref("window.cancelAnimationFrame", "cancelAnimationFrame()")}} (всегда полезно очистить ненужные процессы), и скройте контейнер счетчика.
  • Затем, отобразите абзац с результатами и установите для его текстового содержимого значение "PLAYERS GO!!"  чтобы сообщить игрокам, что теперь они могут нажать свою кнопку, чтобы победить.
  • Прикрепите к документу прослушиватель событий 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.
  • -
  • Только еслиf isOver равно true, удалите прослушиватель событий keydown с помощью {{domxref("EventTarget.removeEventListener", "removeEventListener()")}} чтобы после того, как произошло выигрышное нажатие, больше не было возможности ввода с клавиатуры, чтобы испортить финальный результат игры. Вы также используете setTimeout() для вызова reset() через 5 секунд — как обьяснялось ранее, эта функция сбрасывает игру обратно в исходное состояние, чтобы можно было начать новую игру.
  • +
  • Только если isOver равно true, удалите прослушиватель событий keydown с помощью {{domxref("EventTarget.removeEventListener", "removeEventListener()")}} чтобы после того, как произошло выигрышное нажатие, больше не было возможности ввода с клавиатуры, чтобы испортить финальный результат игры. Вы также используете setTimeout() для вызова reset() через 5 секунд — как объяснялось ранее, эта функция сбрасывает игру обратно в исходное состояние, чтобы можно было начать новую игру.
  • @@ -628,7 +628,7 @@ function start() {