aboutsummaryrefslogtreecommitdiff
path: root/files/he/learn/javascript/asynchronous/timeouts_and_intervals/index.html
diff options
context:
space:
mode:
Diffstat (limited to 'files/he/learn/javascript/asynchronous/timeouts_and_intervals/index.html')
-rw-r--r--files/he/learn/javascript/asynchronous/timeouts_and_intervals/index.html651
1 files changed, 0 insertions, 651 deletions
diff --git a/files/he/learn/javascript/asynchronous/timeouts_and_intervals/index.html b/files/he/learn/javascript/asynchronous/timeouts_and_intervals/index.html
deleted file mode 100644
index 2d97d2827d..0000000000
--- a/files/he/learn/javascript/asynchronous/timeouts_and_intervals/index.html
+++ /dev/null
@@ -1,651 +0,0 @@
----
-title: 'Cooperative asynchronous JavaScript: Timeouts and intervals'
-slug: Learn/JavaScript/Asynchronous/Timeouts_and_intervals
-translation_of: Learn/JavaScript/Asynchronous/Timeouts_and_intervals
----
-<div>{{LearnSidebar}}</div>
-
-<div>{{PreviousMenuNext("Learn/JavaScript/Asynchronous/Introducing", "Learn/JavaScript/Asynchronous/Promises", "Learn/JavaScript/Asynchronous")}}</div>
-
-<p class="summary">
- במאמר זה אנחנו נסתכל על מתודות מסורתיות שיש ב-JavaScript, בעבור הרצה של קוד באופן א-סינכרוני לאחר שזמן מסויים עבר או באינטרוול מסויים (כלומר לקבוע מספר פעמים שירוץ בכל פרק זמן מסויים), נדון בשימושים שלהם ומה הסוגיות הטבועות בהם.
-
- </p>
-
-<table class="learn-box standard-table">
- <tbody>
- <tr>
- <th scope="row">ידע מוקדם:</th>
- <td>Basic computer literacy, a reasonable understanding of JavaScript fundamentals.</td>
- </tr>
- <tr>
- <th scope="row">מטרה:</th>
- <td>
- הבנה של לולאות א-סינכרוניות ואינטרוולים ולמה הם משמים. </td>
- </tr>
- </tbody>
-</table>
-
-<h2 id="הקדמה">הקדמה</h2>
-
-<p>
- במשך זמן רב, פלטפורמת ה-web העניקה למפתחי JavaScript מספר של פונקציות שאפשרו לה להריץ קוד באופן א-סינכרוני, כך שהקוד ירוץ לאחר זמן מסויים שעבר או להריץ קוד מסויים באופן א-סינכרוני,ע ם הפרש זמן מסויים בין כל ריצה שלו, עד שאנחנו נגיד לו לעצור. אלו הם :</p>
-
-<dl>
- <dt><code><a href="/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setTimeout">setTimeout()</a></code></dt>
- <dd>
- מריץ בלוק קוד מסויים פעם אחת לאחר שזמן מסויים עבר. </dd>
- <dt><code><a href="/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setInterval">setInterval()</a></code></dt>
- <dd>
- מריץ בלוק קוד מסויים באופן חוזר, עם הפרש של זמן מסויים בין כל ריצה. </dd>
- <dt><code><a href="/en-US/docs/Web/API/window/requestAnimationFrame">requestAnimationFrame()</a></code></dt>
- <dd>
- זוהי גרסה מודרנית ל-<code>setInterval()</code>. היא מריצה בלוק קוד מסויים לפני שהדפדפן צובע מחדש את התצוגה, כך שמתאפשרת לאניממציה לרוץ במסגרת מתאימה ללא קשר לסביבה בה היא פועלת.
- </dd>
-</dl>
-
-<p>
- הקוד הא-סינכרוני שנכתב באמצעות פונקציות אלו בעצם ירוץ על ה-00000, אבל כן התאפשר לנו להריץ קוד אחר בין כל ריצה שלהם במידה מסוייתמ, תלוי כמה הפונקציות שנכתוב יעשו שימוש רב במעבד. בכל מקרה, הפונקציות הללו משמשות אנימציות קבועות ועוד תהליכי רקע על אתר אינטרנט או יישום אינטרנטר. בחלקים הבאים של המאמר אנחנו נגע בכל אחת מהן ולמה הן משמשות. .</p>
-
-<h2 id="setTimeout()">setTimeout()</h2>
-
-<p>
- כפי שאמרנו למעלה, <code><a href="/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setTimeout">setTimeout()</a></code> מריצה בלוק קוד מסויים פעם אחת, לאחר שזמן מסויים שהגדרנו לה חלף. היא מקבלת את הפרמטרים הבאים: </p>
-
-<ul>
- <li>פונקציה שתרוץ או הפנייה לפונקציה שהוגדרה במקום אחר.
-
- </li>
- <li>
-
- מספר שמייצג את משך הזמן (אינטרוול הזמן) במילשניות (כך 1000 מילישניות שווה לשנייה אחת). המספר הזה מייצג את משך הזמן שיעבור לפני שהקוד יורץ - הפונקציה תורץ. אנחנו יכולים לרשום את הערך של 0 או להשמיט את המספר הזה לחלוטין ואז הפונקציה תרוץ באופן מיידע. עוד על מדוע נרצה לעשות זאת אנחנו נראה בהמשך. </li>
- <li>
- פרמטרים נוספים, ככל ונדרשים על ידי הפונקציה שנתנו כפרמטר ל--<code><a href="/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setTimeout">setTimeout()</a></code>. כלומר, פרמטרים שנרצה להעביר לפונקציה שתרוץ.
-</li>
-</ul>
-
-<div class="blockIndicator note">
-<p><strong>לתשומת לב:</strong>
- מכיוון ש-0000000 מורצות ביחד, אין כל הבטחה שהן יופעלו <em>במדוייק</em> לאחר הזמן שהגדרנו. במקום, הם ייקראו לאחר שהזמן שהגדרנו חלף, <em>לפחות</em>.
-
- Because timeout callbacks are executed cooperatively, there's no guarantee that they will be called after <em>exactly</em> the specified amount of time. Instead, they will be called after <em>at least</em> that much time has elapsed.
-
-
- Timeout handlers לא יכולים לרוץ עד אשר ה-main thread מגיע לנקודה בריצה שלו שם הוא עובר על מטפלים אלו למצוא את אלו שהוא צריך להריץ אותם. שה-00000
-</p>
-</div>
-
-<p>
- בדוגמא הבאה, הדפדפן יחכה שתי שניות לפני שיריץ את הפונקציה האנונימית, ואז יציג את הודעת ה-alert.
-e (<a href="https://mdn.github.io/learning-area/javascript/asynchronous/loops-and-intervals/simple-settimeout.html">ראו כדף אינטרנט</a>, וכן <a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/loops-and-intervals/simple-settimeout.html">את קוד המקור</a>):</p>
-
-<pre class="brush: js">let myGreeting = setTimeout(function() {
- alert('Hello, Mr. Universe!');
-}, 2000)</pre>
-
-<p>
- הפונקציות שאנחנו מציינים לא חייבות להיות אנונימיות. אנחנו יכולים לתת לפונקציה שלנו שם ואפילו להגדיר אותה במקום אחר, ואז להעביר הפנייה לפונקציה בתוך ה- <code>setTimeout()</code> . הגרסאות הבאות של הקוד שלנו הם שוות לראשונה:
-
- he functions we specify don't have to be anonymous. We can give our function a name, and can even define it somewhere else and pass a function reference to the <code>setTimeout()</code>. The following two versions of our code snippet are equivalent to the first one:</p>
-
-<pre class="brush: js">// With a named function
-let myGreeting = setTimeout(function sayHi() {
- alert('Hello, Mr. Universe!');
-}, 2000)
-
-// With a function defined separately
-function sayHi() {
- alert('Hello Mr. Universe!');
-}
-
-let myGreeting = setTimeout(sayHi, 2000);</pre>
-
-<p>
- זה יכול להיות שימושי כאשר יש לנו פונקציה שצריכה להיקרא/להיות מופעלת גם מתוך -timeout וגם בתגובה לאירוע, לדוגמא. אבל, זה גם יכול לעזור לנו להשאיר את הקוד שלנו מסודר, במיוחד אם אחרי ה-timeout callback יש לנו יותר מכמה שורות קוד.
-</p>
-
-<p><code>setTimeout()</code>
- מחזירה ערך מזהה שיכול לשמש לשם הפנייה לאותו timeout לאחר מכן, אם נרצה לדוגמא לעצור את ה-timeout. ראו {{anch("Clearing timeouts")}} בהמשך על מנת ללמוד כיצד לעשות זאת.
-
-
- </p>
-
-<h3 id="העברת_פרמטרים_לפונקציית_setTimeout()">העברת פרמטרים לפונקציית setTimeout() </h3>
-
-<p>
- כל פרמטר שנרצה להעביר לפונקציה שתרוף בתוך ה-<code>setTimeout()</code>, יהיו חייבים להיות מועברים כפרמטרים נוספוים לפונקציית ה-<code>setTimeout()</code>, וזאת בסוף הרשימת פרמטרים. לדוגמא, אנחנו יכולים כתוב מחדש את הפונקציה הקודמת שלנו כך שהיא תגיד hi לכל שם שיועבר אליה
-:</p>
-
-<pre class="brush: js">function sayHi(who) {
- alert('Hello ' + who + '!');
-}</pre>
-
-<p>
- השם של ה-person יכול להיות מועבר כפרמטר שלישי לתוך ה-<code>setTimeout()</code>
-
-:</p>
-
-<pre class="brush: js">let myGreeting = setTimeout(sayHi, 2000, 'Mr. Universe');</pre>
-
-<h3 id="מחיקת_Timeouts">מחיקת Timeouts</h3>
-
-<p>
- לבסוף, אם timeout נוצר, אנחנו יכולים לבטל אותו לפני שהזמן שהגדרנו לו הסתיים באמצעשות שימוש ב-<code><a href="/en-US/docs/Web/API/WindowOrWorkerGlobalScope/clearTimeout">clearTimeout()</a></code> והעברה של אותו ערך מזהה של ה-<code>setTimeout()</code> כפרמטר. כך, על מנת לבטל את ה-<code>setTimeout()</code> בדוגמא למעלה, אנחנו צריכים לרשום משהו כזה:
-</p>
-
-<pre class="brush: js">clearTimeout(myGreeting);</pre>
-
-<div class="blockIndicator note">
-<p><strong>לתשומת לב</strong>: ראו <a href="https://mdn.github.io/learning-area/javascript/asynchronous/loops-and-intervals/greeter-app.html">greeter-app.html</a>
- לדוגמא יותר מעניינת אשר מאפשרת לכן לקבוע את השם של האדם שנגיד לו שלום בטופס, ואז לבטל את הברכה באמצעו תכפתור אחג. (<a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/loops-and-intervals/greeter-app.html">קוד המקור</a>).</p>
-</div>
-
-<h2 id="setInterval()">setInterval()</h2>
-
-<p><code>setTimeout()</code> עובדת מצוים כאשר אנחנו צריכים להריץ בלוק קוד מסויים פעם אחת לאחר אינטרוול זמן שעבר. אבל מה קורה כאשר אנחנו רוצים להריץ קוד מסויים שוב ושוב, כמו במקרה של אנימציות?</p>
-
-<p>כאן נכנס לתמונה <code><a href="/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setInterval">setInterval()</a></code> .
- פונקציה זו עובדת בצורה דומה ל-<code>setTimeout()</code>, למעט העובדה שהפונקציה שאנחנו מעבירים כפרמטר ראשון, תרוץ באופן חוזר ונשנה לכל הפחות בכל משך הזמן שהוגדר לה (גם כן במילישניות), ולא רק פעם אחת. אנחנו גם יכולים להעביר לה את הפרמטרים הדרושים לפונקציה שתרוץ.
-.</p>
-
-<p>
- נראה דוגמא על מנת להמחיש את העניין. הפונקציה הבא יוצרת אובייקט <code><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date">Date()</a></code> חדש, מחלצת חרוזת זמן מתוכו באמצעות שימוש ב- <code><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toLocaleTimeString">toLocaleTimeString()</a></code> ציגה את זה לממשק המתשמש. לאחר מכן אנחנו מריצים פונקציה אחת לשנייה באמצעות שימוש ב-<code>setInterval()</code>
- על מנת ליצור את האפשר של שעון דיגיטלי שמעדכן את עצמו כל שנייה.
- (<a href="https://mdn.github.io/learning-area/javascript/asynchronous/loops-and-intervals/setinterval-clock.html">ראו כדף אינטרנט</a>, ואת also <a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/loops-and-intervals/setinterval-clock.html">קוד המקור</a>):</p>
-
-<pre class="brush: js">function displayTime() {
- let date = new Date();
- let time = date.toLocaleTimeString();
- document.getElementById('demo').textContent = time;
-}
-
-const createClock = setInterval(displayTime, 1000);</pre>
-
-<p>בדיוק כמו <code>setTimeout()</code>, <code>setInterval()</code> מחזירה ערך מזהה כך שאנחנו יכולים להשתמש בו בהמשך על מנת למחוק את ה-interval.</p>
-
-<h3 id="מחיקת_intervals">מחיקת intervals</h3>
-
-<p><code>setInterval()</code> תמשיך לרוץ באופן מתמשך וקבוע, אלא אם אנחנו נעשה איתה משהו -
- אנחנו נרצה אולי דרך לעצור משימות כאלו, אחרת אנחנו נקבל שגיאות השהדפדפן לא מצליח להשלים גרסאות נוספות של המשימה הזו, או שהאניממציה שמטופלת על ידי המשימה הזו הסתיימה. אנחנו יכולים לעשות זאת באותה דרך שבה אנחנו מסיימים <code>setInterval()</code> - באמצעות העבר הערך המזהה שהוחזר לנו בהפעלה של <code>setInterval()</code> לפונקציה <code><a href="/en-US/docs/Web/API/WindowOrWorkerGlobalScope/clearInterval">clearInterval()</a></code>:
-
- </p>
-
-<pre class="brush: js">const myInterval = setInterval(myFunction, 2000);
-
-clearInterval(myInterval);</pre>
-
-<h4 id="למידה_עצמאית_יצירה_של_שעון_עצר">למידה עצמאית: יצירה של שעון עצר</h4>
-
-<p>לאחר שעברנו על פונקציות אלו, נסו לאתגר את עצמכם במשימה זו. עשו עותקשל הדוגמא שלנו שנמצא ב- <a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/loops-and-intervals/setinterval-clock.html">setInterval-clock.html</a> ושנו אותה כך שתהיה שעון סטופר.</p>
-
-<p>
- אתם צריכים להציג את הזמן כמו בדוגמא הקודמת, רק שבתרגיל זה אתם תצטרכו:</p>
-
-<ul>
- <li>כפתור "Start" על מנת שהשעון יתחיל לרוץ.</li>
- <li>כפתור "Stop" להשהות את השעון.</li>
- <li>כפתור "Reset" לאפס את השעון ל- 0.</li>
- <li>תצוגת זמן על מנת להציג כמה שניות עברו ולא מה השעה הנוכחית </li>
-</ul>
-
-<p>רמזים:</p>
-
-<ul>
- <li>You can structure and style the button markup however you like; just make sure you use semantic HTML, with hooks to allow you to grab the button references using JavaScript.</li>
- <li>You probably want to create a variable that starts at 0, then increments by one every second using a constant loop.</li>
- <li>It is easier to create this example without using a <code>Date()</code> object, like we've done in our version, but less accurate — you can't guarantee that the callback will fire after exactly 1000ms. A more accurate way would be to run <code>startTime = Date.now()</code> to get a timestamp of exactly when the user clicked the start button, and then do <code>Date.now() - startTime</code> to get the number of milliseconds after the start button was clicked.</li>
- <li>You also want to calculate the number of hours, minutes, and seconds as separate values, and then show them together in a string after each loop iteration. From the second counter, you can work out each of these.</li>
- <li>How would you calculate them? Have a think about it:
- <ul>
- <li>The number of seconds in an hour is 3600.</li>
- <li>The number of minutes will be the amount of seconds left over when all of the hours have been removed, divided by 60.</li>
- <li>The number of seconds will be the amount of seconds left over when all of the minutes have been removed.</li>
- </ul>
- </li>
- <li>You'll want to include a leading zero on your display values if the amount is less than 10, so it looks more like a traditional clock/watch.</li>
- <li>To pause the stopwatch, you'll want to clear the interval. To reset it, you'll want to set the counter back to 0 and then immediately update the display.</li>
- <li>You probably ought to disable the start button after pressing it once, and enable it again after you've stopped it. Otherwise multiple presses of the start button will apply multiple <code>setInterval()</code>s to the clock, leading to wrong behavior.</li>
-</ul>
-
-<div class="blockIndicator note">
-<p><strong>Note</strong>: If you get stuck, you can <a href="https://mdn.github.io/learning-area/javascript/asynchronous/loops-and-intervals/setinterval-stopwatch.html">find our version here</a> (see the <a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/loops-and-intervals/setinterval-stopwatch.html">source code</a> also).</p>
-</div>
-
-<h2 id="Things_to_keep_in_mind_about_setTimeout()_and_setInterval()">Things to keep in mind about setTimeout() and setInterval()</h2>
-
-<p>There are a few things to keep in mind when working with <code>setTimeout()</code> and <code>setInterval()</code>. Let's review these now.</p>
-
-<h3 id="Recursive_timeouts">Recursive timeouts</h3>
-
-<p>There is another way we can use <code>setTimeout()</code>: We can call it recursively to run the same code repeatedly, instead of using <code>setInterval()</code>.</p>
-
-<p>The below example uses a recursive <code>setTimeout()</code> to run the passed function every 100 milliseconds:</p>
-
-<pre class="brush: js">let i = 1;
-
-setTimeout(function run() {
- console.log(i);
- i++;
- setTimeout(run, 100);
-}, 100);</pre>
-
-<p>Compare the above example to the following one — this uses <code>setInterval()</code> to accomplish the same effect:</p>
-
-<pre class="brush: js">let i = 1;
-
-setInterval(function run() {
- console.log(i);
- i++
-}, 100);</pre>
-
-<h4 id="How_do_recursive_setTimeout()_and_setInterval()_differ">How do recursive <code>setTimeout()</code> and <code>setInterval()</code> differ?</h4>
-
-<p>The difference between the two versions of the above code is a subtle one.</p>
-
-<ul>
- <li>Recursive <code>setTimeout()</code> guarantees the same delay between the executions, so for example 100ms in the above case. The code will run and then wait 100 milliseconds before it runs again, so the interval will be the same regardless of how long the code takes to run.</li>
- <li>The example using <code>setInterval()</code> does things somewhat differently. The interval we choose <em>includes</em> the time taken to execute the code we want to run in. Let's say that the code takes 40 milliseconds to run — the interval then ends up being only 60 milliseconds.</li>
- <li>When using <code>setTimeout()</code> recursively, each iteration can calculate a different delay before running the next iteration. In other words, the value of the second parameter can specify a different time in milliseconds to wait before running the code again.</li>
-</ul>
-
-<p>When your code has the potential to take longer to run than the time interval you’ve assigned, it’s better to use recursive <code>setTimeout()</code> — this will keep the time interval constant between executions regardless of how long the code takes to execute, and you won't get errors.</p>
-
-<h3 id="Immediate_timeouts">Immediate timeouts</h3>
-
-<p>Using 0 as the value for <code>setTimeout()</code> schedules the execution of the specified callback function as soon as possible but only after the main code thread has been run.</p>
-
-<p>For instance, the code below (<a href="https://mdn.github.io/learning-area/javascript/asynchronous/loops-and-intervals/zero-settimeout.html">see it live</a>) outputs an alert containing "Hello", then an alert containing "World" as soon as you click OK on the first alert.</p>
-
-<pre class="brush: js">setTimeout(function() {
- alert('World');
-}, 0);
-
-alert('Hello');</pre>
-
-<p>This can be useful in cases where you want to set a block of code to run as soon as all of the main thread has finished running — put it on the async event loop, so it will run straight afterwards.</p>
-
-<h3 id="Clearing_with_clearTimeout()_or_clearInterval()">Clearing with clearTimeout() or clearInterval()</h3>
-
-<p><code>clearTimeout()</code> and <code>clearInterval()</code> both use the same list of entries to clear from. Interestingly enough, this means that you can use either method to clear a <code>setTimeout()</code> or <code>setInterval()</code>.</p>
-
-<p>For consistency, you should use <code>clearTimeout()</code> to clear <code>setTimeout()</code> entries and <code>clearInterval()</code> to clear <code>setInterval()</code> entries. This will help to avoid confusion.</p>
-
-<h2 id="requestAnimationFrame()">requestAnimationFrame()</h2>
-
-<p><code><a href="/en-US/docs/Web/API/window/requestAnimationFrame">requestAnimationFrame()</a></code> is a specialized looping function created for running animations efficiently in the browser. It is basically the modern version of <code>setInterval()</code> — it executes a specified block of code before the browser next repaints the display, allowing an animation to be run at a suitable frame rate regardless of the environment it is being run in.</p>
-
-<p>It was created in response to perceived problems with <code>setInterval()</code>, which for example doesn't run at a frame rate optimized for the device, sometimes drops frames, continues to run even if the tab is not the active tab or the animation is scrolled off the page, etc. <a href="http://creativejs.com/resources/requestanimationframe/index.html">Read more about this on CreativeJS</a>.</p>
-
-<div class="blockIndicator note">
-<p><strong>Note</strong>: You can find examples of using <code>requestAnimationFrame()</code> elsewhere in the course — see for example <a href="/en-US/docs/Learn/JavaScript/Client-side_web_APIs/Drawing_graphics">Drawing graphics</a>, and <a href="/en-US/docs/Learn/JavaScript/Objects/Object_building_practice">Object building practice</a>.</p>
-</div>
-
-<p>The method takes as an argument a callback to be invoked before the repaint. This is the general pattern you'll see it used in:</p>
-
-<pre class="brush: js">function draw() {
- // Drawing code goes here
- requestAnimationFrame(draw);
-}
-
-draw();</pre>
-
-<p>The idea is that you define a function in which your animation is updated (e.g. your sprites are moved, score is updated, data is refreshed, or whatever), then you call it to start the process off. At the end of the function block you call <code>requestAnimationFrame()</code> with the function reference passed as the parameter, and this instructs the browser to call the function again on the next display repaint. This is then run continuously, as we are calling <code>requestAnimationFrame()</code> recursively.</p>
-
-<div class="blockIndicator note">
-<p><strong>Note</strong>: If you want to perform some kind of simple constant DOM animation, <a href="/en-US/docs/Web/CSS/CSS_Animations">CSS Animations</a> are probably faster as they are calculated directly by the browser's internal code rather than JavaScript. If however you are doing something more complex and involving objects that are not directly accessible inside the DOM (such as <a href="/en-US/docs/Web/API/Canvas_API">2D Canvas API</a> or <a href="/en-US/docs/Web/API/WebGL_API">WebGL</a> objects), <code>requestAnimationFrame()</code> is the better option in most cases.</p>
-</div>
-
-<h3 id="How_fast_does_your_animation_run">How fast does your animation run?</h3>
-
-<p>The smoothness of your animation is directly dependent on your animation's frame rate and it is measured in frames per second (fps). The higher this number is, the smoother your animation will look, to a point.</p>
-
-<p>Since most screens have a refresh rate of 60Hz, the fastest frame rate you can aim for is 60 frames per second (FPS) when working with web browsers. However, more frames means more processing, which can often cause stuttering and skipping — also known as <em>dropping frames</em>, or <em>jank</em>.</p>
-
-<p>If you have a monitor with a 60Hz refresh rate and you want to achieve 60 FPS you have about 16.7 milliseconds (1000 / 60) to execute your animation code to render each frame. This is a reminder that we need to be mindful of the amount of code that we try to run for each pass through the animation loop.</p>
-
-<p><code>requestAnimationFrame()</code> always tries to get as close to this magic 60 FPS value as possible, although sometimes it isn't possible — if you have a really complex animation and you are running it on a slow computer, your frame rate will be less. <code>requestAnimationFrame()</code> will always do the best it can with what it has available.</p>
-
-<h3 id="How_does_requestAnimationFrame()_differ_from_setInterval()_and_setTimeout()">How does requestAnimationFrame() differ from setInterval() and setTimeout()?</h3>
-
-<p>Let's talk a little bit more about how the <code>requestAnimationFrame()</code> method differs from the other methods we looked at earlier. Looking at our code from above:</p>
-
-<pre class="brush: js">function draw() {
- // Drawing code goes here
- requestAnimationFrame(draw);
-}
-
-draw();</pre>
-
-<p>Let's now see how we'd do the same thing using <code>setInterval()</code>:</p>
-
-<pre class="brush: js">function draw() {
- // Drawing code goes here
-}
-
-setInterval(draw, 17);</pre>
-
-<p>As we said before, we don't specify a time interval for <code>requestAnimationFrame()</code>; it just runs it as quickly and smoothly as possible in the current conditions. The browser also doesn't waste time running it if the animation is offscreen for some reason, etc.</p>
-
-<p><code>setInterval()</code> on the other hand requires an interval to be specified. We arrived at our final value of 17 via the formula <em>1000 milliseconds / 60Hz</em>, and then rounded it up. Rounding up is a good idea, as if you rounded down the browser might try to run the animation faster than 60fps, and it wouldn't make any difference to the smoothness of the animation anyway. As we said before, 60Hz is the standard refresh rate.</p>
-
-<h3 id="Including_a_timestamp">Including a timestamp</h3>
-
-<p>The actual callback passed to the <code>requestAnimationFrame()</code> function can be given a parameter too — a timestamp value that represents the time since the <code>requestAnimationFrame()</code> started running. This is useful as it allows you to run things at specific times and at a constant pace, regardless of how fast or slow your device might be. The general pattern you'd use looks something like this:</p>
-
-<pre class="brush: js">let startTime = null;
-
-function draw(timestamp) {
- if(!startTime) {
- startTime = timestamp;
- }
-
- currentTime = timestamp - startTime;
-
- // Do something based on current time
-
- requestAnimationFrame(draw);
-}
-
-draw();</pre>
-
-<h3 id="Browser_support">Browser support</h3>
-
-<p><code>requestAnimationFrame()</code> is supported in slightly more recent browsers than <code>setInterval()</code>/<code>setTimeout()</code> — most interestingly it is available in Internet Explorer 10 and above. So unless you need to support older versions of IE with your code, there is little reason to not use <code>requestAnimationFrame()</code>.</p>
-
-<h3 id="A_simple_example">A simple example</h3>
-
-<p>Enough with the theory; let's go through and build our own <code>requestAnimationFrame()</code> example. We're going to create a simple "spinner animation", the kind you might see displayed in an app when it is busy connecting to the server, etc.</p>
-
-<div class="blockIndicator note">
-<p><strong>Note</strong>: In a real world example, you should probably use CSS animations to run this kind of simple animation. However, this kind of example is very useful to demonstrate <code>requestAnimationFrame()</code> usage, and you'd be more like to use this kind of technique when doing something more complex such as updating the display of a game on each frame.</p>
-</div>
-
-<ol>
- <li>
- <p>First of all, grab a basic HTML template <a href="https://github.com/mdn/learning-area/blob/master/html/introduction-to-html/getting-started/index.html">such as this one</a>.</p>
- </li>
- <li>
- <p>Put an empty {{htmlelement("div")}} element inside the {{htmlelement("body")}}, then add a ↻ character inside it. This is a circular arrow character that will act as our spinner for this simple example.</p>
- </li>
- <li>
- <p>Apply the following CSS to the HTML template in whatever way you prefer. This sets a red background on the page, sets the <code>&lt;body&gt;</code> height to <code>100%</code> of the {{htmlelement("html")}} height, and centers the <code>&lt;div&gt;</code> inside the <code>&lt;body&gt;</code>, horizontally and vertically.</p>
-
- <pre class="brush: css">html {
- background-color: white;
- height: 100%;
-}
-
-body {
- height: inherit;
- background-color: red;
- margin: 0;
- display: flex;
- justify-content: center;
- align-items: center;
-}
-
-div {
- display: inline-block;
- font-size: 10rem;
-}</pre>
- </li>
- <li>
- <p>Insert a {{htmlelement("script")}} element just above the <code>&lt;/body&gt;</code> tag.</p>
- </li>
- <li>
- <p>Insert the following JavaScript inside your <code>&lt;script&gt;</code> element. Here we're storing a reference to the <code>&lt;div&gt;</code> inside a constant, setting a <code>rotateCount</code> variable to 0, setting an uninitialized variable that will later be used to contain a reference to the <code>requestAnimationFrame()</code> call, and setting a <code>startTime</code> variable to <code>null</code>, which will later be used to store the start time of the <code>requestAnimationFrame()</code>.</p>
-
- <pre class="brush: js">const spinner = document.querySelector('div');
-let rotateCount = 0;
-let startTime = null;
-let rAF;
-</pre>
- </li>
- <li>
- <p>Below the previous code, insert a <code>draw()</code> function that will be used to contain our animation code, which includes the <code>timestamp</code> parameter:</p>
-
- <pre class="brush: js">function draw(timestamp) {
-
-}</pre>
- </li>
- <li>
- <p>Inside <code>draw()</code>, add the following lines. Here we define the start time if it is not defined already (this will only happen on the first loop iteration), and set the <code>rotateCount</code> to a value to rotate the spinner by (the current timestamp, take the starting timestamp, divided by three so it doesn't go too fast):</p>
-
- <pre class="brush: js"> if (!startTime) {
- startTime = timestamp;
- }
-
- rotateCount = (timestamp - startTime) / 3;
-</pre>
- </li>
- <li>
- <p>Below the previous line inside <code>draw()</code>, add the following block — this checks to see if the value of <code>rotateCount</code> is above <code>359</code> (e.g. <code>360</code>, a full circle). If so, it sets the value to its modulo of 360 (i.e. the remainder left over when the value is divided by 360) so the circle animation can continue uninterrupted, at a sensible, low value. Note that this isn't strictly necessary, but it is easier to work with values of 0-359 degrees than values like "128000 degrees".</p>
-
- <pre class="brush: js">if (rotateCount &gt; 359) {
- rotateCount %= 360;
-}</pre>
- </li>
- <li>Next, below the previous block add the following line to actually rotate the spinner:
- <pre class="brush: js">spinner.style.transform = 'rotate(' + rotateCount + 'deg)';</pre>
- </li>
- <li>
- <p>At the very bottom inside the <code>draw()</code> function, insert the following line. This is the key to the whole operation — we are setting the variable we defined earlier to an active <code>requestAnimation()</code> call that takes the <code>draw()</code> function as its parameter. This starts the animation off, constantly running the <code>draw()</code> function at a rate of as close to 60 FPS as possible.</p>
-
- <pre class="brush: js">rAF = requestAnimationFrame(draw);</pre>
- </li>
-</ol>
-
-<div class="blockIndicator note">
-<p><strong>Note</strong>: You can find this <a href="https://mdn.github.io/learning-area/javascript/asynchronous/loops-and-intervals/simple-raf-spinner.html">example live on GitHub</a> (see the <a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/loops-and-intervals/simple-raf-spinner.html">source code</a> also).</p>
-</div>
-
-<h3 id="Clearing_a_requestAnimationFrame()_call">Clearing a requestAnimationFrame() call</h3>
-
-<p>Clearing a <code>requestAnimationFrame()</code> call can be done by calling the corresponding <code>cancelAnimationFrame()</code> method (note, "cancel" not "clear" as with the "set..." methods), passing it the value returned by the <code>requestAnimationFrame()</code> call to cancel, which we stored in a variable called <code>rAF</code>:</p>
-
-<pre class="brush: js">cancelAnimationFrame(rAF);</pre>
-
-<h3 id="Active_learning_Starting_and_stopping_our_spinner">Active learning: Starting and stopping our spinner</h3>
-
-<p>In this exercise, we'd like you to test out the <code>cancelAnimationFrame()</code> method by taking our previous example and updating it, adding an event listener to start and stop the spinner when the mouse is clicked anywhere on the page.</p>
-
-<p>Some hints:</p>
-
-<ul>
- <li>A <code>click</code> event handler can be added to most elements, including the document <code>&lt;body&gt;</code>. It makes more sense to put it on the <code>&lt;body&gt;</code> element if you want to maximize the clickable area — the event bubbles up to its child elements.</li>
- <li>You'll want to add a tracking variable to check whether the spinner is spinning or not, clearing the animation frame if it is, and calling it again if it isn't.</li>
-</ul>
-
-<div class="blockIndicator note">
-<p><strong>Note</strong>: Try this yourself first; if you get really stuck, check out of our <a href="https://mdn.github.io/learning-area/javascript/asynchronous/loops-and-intervals/start-and-stop-spinner.html">live example</a> and <a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/loops-and-intervals/start-and-stop-spinner.html">source code</a>.</p>
-</div>
-
-<h3 id="Throttling_a_requestAnimationFrame()_animation">Throttling a requestAnimationFrame() animation</h3>
-
-<p>One limitation of <code>requestAnimationFrame()</code> is that you can't choose your frame rate. This isn't a problem most of the time, as generally you want your animation to run as smoothly as possible, but what about when you want to create an old school, 8-bit-style animation?</p>
-
-<p>This was a problem for example in the Monkey Island-inspired walking animation from our <a href="/en-US/docs/Learn/JavaScript/Client-side_web_APIs/Drawing_graphics">Drawing Graphics</a> article:</p>
-
-<p>{{EmbedGHLiveSample("learning-area/javascript/apis/drawing-graphics/loops_animation/7_canvas_walking_animation.html", '100%', 260)}}</p>
-
-<p>In this example we have to animate both the position of the character on the screen, and the sprite being shown. There are only 6 frames in the sprite's animation; if we showed a different sprite frame for every frame displayed on the screen by <code>requestAnimationFrame()</code>, Guybrush would move his limbs too fast and the animation would look ridiculous. We therefore throttled the rate at which the sprite cycles its frames using the following code:</p>
-
-<pre class="brush: js">if (posX % 13 === 0) {
- if (sprite === 5) {
- sprite = 0;
- } else {
- sprite++;
- }
-}</pre>
-
-<p>So we are only cycling a sprite once every 13 animation frames. OK, so it's actually about every 6.5 frames, as we update <code>posX</code> (character's position on the screen) by two each frame:</p>
-
-<pre class="brush: js">if(posX &gt; width/2) {
- newStartPos = -((width/2) + 102);
- posX = Math.ceil(newStartPos / 13) * 13;
- console.log(posX);
-} else {
- posX += 2;
-}</pre>
-
-<p>This is the code that works out how to update the position in each animation frame.</p>
-
-<p>The method you use to throttle your animation will depend on your particular code. For example, in our spinner example we could make it appear to move slower by only increasing our <code>rotateCount</code> by one on each frame instead of two.</p>
-
-<h2 id="Active_learning_a_reaction_game">Active learning: a reaction game</h2>
-
-<p>For our final section of this article, we'll create a 2-player reaction game. Here we have two players, one of whom controls the game using the <kbd>A</kbd> key, and the other with the <kbd>L</kbd> key.</p>
-
-<p>When the <em>Start</em> button is pressed, a spinner like the one we saw earlier is displayed for a random amount of time between 5 and 10 seconds. After that time, a message will appear saying "PLAYERS GO!!" — once this happens, the first player to press their control button will win the game.</p>
-
-<p>{{EmbedGHLiveSample("learning-area/javascript/asynchronous/loops-and-intervals/reaction-game.html", '100%', 500)}}</p>
-
-<p>Let's work through this.</p>
-
-<ol>
- <li>
- <p>First of all, download the <a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/loops-and-intervals/reaction-game-starter.html">starter file for the app</a> — this contains the finished HTML structure and CSS styling, giving us a game board that shows the two players' information (as seen above), but with the spinner and results paragraph displayed on top of one another. We just have to write the JavaScript code.</p>
- </li>
- <li>
- <p>Inside the empty {{htmlelement("script")}} element on your page, start by adding the following lines of code that define some constants and variables we'll need in the rest of the code:</p>
-
- <pre class="brush: js">const spinner = document.querySelector('.spinner p');
-const spinnerContainer = document.querySelector('.spinner');
-let rotateCount = 0;
-let startTime = null;
-let rAF;
-const btn = document.querySelector('button');
-const result = document.querySelector('.result');</pre>
-
- <p>In order, these are:</p>
-
- <ol>
- <li>A reference to our spinner, so we can animate it.</li>
- <li>A reference to the {{htmlelement("div")}} element that contains the spinner, used for showing and hiding it.</li>
- <li>A rotate count — how much we want to show the spinner rotated on each frame of the animation.</li>
- <li>A null start time — will be populated with a start time when the spinner starts spinning.</li>
- <li>An uninitialized variable to later store the {{domxref("Window.requestAnimationFrame", "requestAnimationFrame()")}} call that animates the spinner.</li>
- <li>A reference to the Start button.</li>
- <li>A reference to the results paragraph.</li>
- </ol>
- </li>
- <li>
- <p>Next, below the previous lines of code, add the following function. This simply takes two numerical inputs and returns a random number between the two. We'll need this to generate a random timeout interval later on.</p>
-
- <pre class="brush: js">function random(min,max) {
- var num = Math.floor(Math.random()*(max-min)) + min;
- return num;
-}</pre>
- </li>
- <li>
- <p>Next add in the <code>draw()</code> function, which animates the spinner. This is exactly the same as the version seen in the simple spinner example we looked at earlier:</p>
-
- <pre class="brush: js"> function draw(timestamp) {
- if(!startTime) {
- startTime = timestamp;
- }
-
- let rotateCount = (timestamp - startTime) / 3;
- spinner.style.transform = 'rotate(' + rotateCount + 'deg)';
-
- if(rotateCount &gt; 359) {
- rotateCount -= 360;
- }
-
- rAF = requestAnimationFrame(draw);
- }</pre>
- </li>
- <li>
- <p>Now it is time to set up the initial state of the app when the page first loads. Add the following two lines, which simply hide the results paragraph and spinner container using <code>display: none;</code>.</p>
-
- <pre class="brush: js">result.style.display = 'none';
-spinnerContainer.style.display = 'none';</pre>
- </li>
- <li>
- <p>We'll also define a <code>reset()</code> function, which sets the app back to the original state required to start the game again after it has been played. Add the following at the bottom of your code:</p>
-
- <pre class="brush: js">function reset() {
- btn.style.display = 'block';
- result.textContent = '';
- result.style.display = 'none';
-}</pre>
- </li>
- <li>
- <p>OK, enough preparation.  Let's make the game playable! Add the following block to your code. The <code>start()</code> function calls <code>draw()</code> to start the spinner spinning and display it in the UI, hides the <em>Start</em> button so we can't mess up the game by starting it multiple times concurrently, and runs a <code>setTimeout()</code> call that runs a <code>setEndgame()</code> function after a random interval between 5 and 10 seconds has passed. We also add an event listener to our button to run the <code>start()</code> function when it is clicked.</p>
-
- <pre class="brush: js">btn.addEventListener('click', start);
-
-function start() {
- draw();
- spinnerContainer.style.display = 'block';
- btn.style.display = 'none';
- setTimeout(setEndgame, random(5000,10000));
-}</pre>
-
- <div class="blockIndicator note">
- <p><strong>Note</strong>: You'll see that in this example we are calling <code>setTimeout()</code> without storing the return value (so not <code>let myTimeout = setTimeout(functionName, interval)</code>). This works and is fine, as long as you don't need to clear your interval/timeout at any point. If you do, you'll need to save the returned identifier.</p>
- </div>
-
- <p>The net result of the previous code is that when the <em>Start</em> button is pressed, the spinner is shown and the players are made to wait a random amount of time before they are then asked to press their button. This last part is handled by the <code>setEndgame()</code> function, which we should define next.</p>
- </li>
- <li>
- <p>So add the following function to your code next:</p>
-
- <pre class="brush: js">function setEndgame() {
- cancelAnimationFrame(rAF);
- spinnerContainer.style.display = 'none';
- result.style.display = 'block';
- result.textContent = 'PLAYERS GO!!';
-
- document.addEventListener('keydown', keyHandler);
-
- function keyHandler(e) {
- console.log(e.key);
- if(e.key === 'a') {
- result.textContent = 'Player 1 won!!';
- } else if(e.key === 'l') {
- result.textContent = 'Player 2 won!!';
- }
-
- document.removeEventListener('keydown', keyHandler);
- setTimeout(reset, 5000);
- };
-}</pre>
-
- <p>Stepping through this:</p>
-
- <ol>
- <li>First we cancel the spinner animation with {{domxref("window.cancelAnimationFrame", "cancelAnimationFrame()")}} (it is always good to clean up unneeded processes), and hide the spinner container.</li>
- <li>Next we display the results paragraph and set its text content to "PLAYERS GO!!" to signal to the players that they can now press their button to win.</li>
- <li>We then attach a <code><a href="/en-US/docs/Web/API/Document/keydown_event">keydown</a></code> event listener to our document — when any button is pressed down, the <code>keyHandler()</code> function is run.</li>
- <li>Inside <code>keyHandler()</code>, we include the event object as a parameter (represented by <code>e</code>) — its {{domxref("KeyboardEvent.key", "key")}} property contains the key that was just pressed, and we can use this to respond to specific key presses with specific actions.</li>
- <li>We first log <code>e.key</code> to the console, which is a useful way of finding out the <code>key</code> value of different keys you are pressing.</li>
- <li>When <code>e.key</code> is "a", we display a message to say that Player 1 won, and when <code>e.key</code> is "l", we display a message to say Player 2 won. Note that this will only work with lowercase a and l — if an uppercase A or L is submitted (the key plus <kbd>Shift</kbd>), it is counted as a different key.</li>
- <li>Regardless of which one of the player control keys was pressed, we remove the <code>keydown</code> event listener using {{domxref("EventTarget.removeEventListener", "removeEventListener()")}} so that once the winning press has happened, no more keyboard input is possible to mess up the final game result. We also use <code>setTimeout()</code> to call <code>reset()</code> after 5 seconds — as we explained earlier, this function resets the game back to its original state so that a new game can be started.</li>
- </ol>
- </li>
-</ol>
-
-<p>That's it, you're all done.</p>
-
-<div class="blockIndicator note">
-<p><strong>Note</strong>: If you get stuck, check out <a href="https://mdn.github.io/learning-area/javascript/asynchronous/loops-and-intervals/reaction-game.html">our version of the reaction game</a> (see the <a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/loops-and-intervals/reaction-game.html">source code</a> also).</p>
-</div>
-
-<h2 id="Conclusion">Conclusion</h2>
-
-<p>So that's it — all the essentials of async loops and intervals covered in one article. You'll find these methods useful in a lot of situations, but take care not to overuse them — since these still run on the main thread, heavy and intensive callbacks (especially those that manipulate the DOM) can really slow down a page if you're not careful.</p>
-
-<p>{{PreviousMenuNext("Learn/JavaScript/Asynchronous/Introducing", "Learn/JavaScript/Asynchronous/Promises", "Learn/JavaScript/Asynchronous")}}</p>
-
-
-<h2 id="במודול_זה">במודול זה</h2>
-
-<ul>
- <li><a href="/he/docs/Learn/JavaScript/Asynchronous/Concepts">עקרונות תכנות א-סינכרוני כלליים</a></li>
- <li><a href="/he/docs/Learn/JavaScript/Asynchronous/Introducing">הצגת asynchronous JavaScript</a></li>
- <li><a href="/he/docs/Learn/JavaScript/Asynchronous/Timeouts_and_intervals">Asynchronous JavaScript: שימוש ב-Intervals ו-Timeouts</a></li>
- <li><a href="/he/docs/Learn/JavaScript/Asynchronous/Promises">טיפול בפעולות א-סינכרוניות באמצעות Promises</a></li>
- <li><a href="/he/docs/Learn/JavaScript/Asynchronous/Async_await">הפיכת Asynchronous Programming לקל יותר עם async ועם await</a></li>
- <li><a href="/he/docs/Learn/JavaScript/Asynchronous/Choosing_the_right_approach">בחירת האפשרות המתאימה</a></li>
-</ul>