1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
|
---
title: הצגת asynchronous JavaScript
slug: Learn/JavaScript/Asynchronous/Introducing
translation_of: Learn/JavaScript/Asynchronous/Introducing
---
<div>{{LearnSidebar}}</div>
<div>{{PreviousMenuNext("Learn/JavaScript/Asynchronous/Concepts", "Learn/JavaScript/Asynchronous/Timeouts_and_intervals", "Learn/JavaScript/Asynchronous")}}</div>
<p class="summary">במאמר זה אנחנו נסקור שוב את הבעיות הקשורות ב-Synchronous 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>להבין מהי שAsynchronous JavaScript וכיצד היא שונה מ-Synchronous JavaScript, ומתי להשתמש בה.</td>
</tr>
</tbody>
</table>
<h2 id="Synchronous_JavaScript">Synchronous JavaScript</h2>
<p>על מנת שנוכל להבין מה זה <strong>{{Glossary("asynchronous")}}</strong> JavaScript אנחנו צריכים תחילה להבין מה זה <strong>{{Glossary("synchronous")}}</strong> JavaScript. חלק זה של המאמר יסקור שוב חלק מהמידע שכבר עברנו עליו במאמר הקודם.</p>
<p>הרבה מהפונקציונליות שראינו במודולים הקודמים של מדריך זה היו דיי סינכרוניים - אנחנו מריצים קוד מסויים והתוצאה של אותה ריצה מוחזרת כאשר הדפדפן יכול להחזיר את התוצאה. נסתכל כעת על דוגמא פשוטה ב-<a href="https://mdn.github.io/learning-area/javascript/asynchronous/introducing/simple-sync.html">דף זה</a>, <a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/introducing/simple-sync.html">או בקוד המקור</a>:</p>
<pre class="brush: js notranslate">const btn = document.querySelector('button');
btn.addEventListener('click', () => {
alert('You clicked me!');
let pElem = document.createElement('p');
pElem.textContent = 'This is a newly-added paragraph.';
document.body.appendChild(pElem);
});
</pre>
<p>בקוד זה, השורות מורצות אחת אחרי השנייה:</p>
<ol>
<li>אנחנו יוצרים הפנייה לאלמנט {{htmlelement("button")}} שכבר זמין ב-DOM.</li>
<li>אנחנו מוסיפים מטפל אירוע בשם <code><a href="/en-US/docs/Web/API/Element/click_event">click</a></code> כך שכאשר הכפתור נלחץ:
<ol>
<li>הודעת <code><a href="/en-US/docs/Web/API/Window/alert">()alert</a></code> מוצגת למשתמש.</li>
<li>ברגע שהודעה זו נסגרת, אנחנו יוצרים אלמנט {{htmlelement("p")}}.</li>
<li>לאחר מכן אנחנו מכניסים לתוך האלמנט {{htmlelement("p")}} תוכן.</li>
<li>בסוף אנחנו משייכים את ה- {{htmlelement("p")}} ל-body.</li>
</ol>
</li>
</ol>
<p>בעוד שכל תהליך שכזה נמצא בהרצה או עיבוד, שום דבר אחר לא יכול להתרחש - יתר העיבוד מושהה. זה מכיוון שכפי שראינו ב<a href="/he/docs/Learn/JavaScript/Asynchronous/Introducing">מאמר הקודם</a> ש-<a href="/en-US/docs/Learn/JavaScript/Asynchronous/Concepts#JavaScript_is_single_threaded">JavaScript היא single threaded</a>. רק דבר אחד יכול להתרחש בכל פעם על ה-single main thread, וכל היתר חסום לביצוע או לעיבוד עד אשר אותה פעולה תושלם.</p>
<p>בדוגמא למעלה, אחרי שלחצנו על הכפתור, הפסקה לא הופיעה עד לאחר שכפתור ה-OK לא נלחץ בחלונית הקופצת. אתם יכולים לנסות זאת בעצמכם:</p>
<div class="hidden">
<pre class="brush: html notranslate"><<span class="pl-ent">button</span>>Click me</<span class="pl-ent">button</span>></pre>
</div>
<p>{{EmbedLiveSample('Synchronous_JavaScript', '100%', '70px')}}</p>
<div class="blockIndicator note">
<p><strong>לתשומת לב</strong>: חשוב לזכור שאמנם <code><a href="/en-US/docs/Web/API/Window/alert">()alert</a></code> מאוד שימושי לשם הסבר על פעולות סינכרוניות שחוסמות את המשך הפעילות, זוהי פונקציה שאינה בשימוש רב ביישומים אמיתיים מטעמים של חווית משתמש לרוב.</p>
</div>
<h2 id="Asynchronous_JavaScript">Asynchronous JavaScript</h2>
<p>לאור הסיבות שנסקרו למעלה, הרבה Web API משתמשים בקוד א-סינכרוני על מנת לפעול, במיוחד אלו שניגשים או מביאים משאב מסויים מגורם חיצוני, כמו הבאה של קובץ מהרשת, גישה למאגר מידע והחזרת מידע מתוכו, הפעלת של הזרמת וידאו באמצעות מצלמת רשת וכד׳.</p>
<p>מדוע העבודה עם קוד א-סינכרוני היא מורכבת? נסתכל על דוגמא זריזה. כאשר אנחנו מבקשים תמונה משרת מסויים, איננו יכולים לקבל את התשובה באופן מיידי. זה אומר שהפסאודו-קוד הרשום להלן לא יעבוד:</p>
<pre class="brush: js notranslate">var response = fetch('myImage.png');
var blob = response.blob();
// display your image blob in the UI somehow</pre>
<p>זה מכיוון שאנחנו לא יודעים כמה זמן ייקח לתמונה להגיע מהשרת, אז כאשר אנחנו נרצה להריץ את שורת הקוד הבאה, היא תחזיר לנו שגיאה (אולי לסירוגין, אולי בכל פעם) מכיוון שה-<code>response</code> אינו זמין עבורנו עדיין. במקום זאת, אנחנו צריכים שהקוד שלנו יחכה ל-<code>response</code> שיוחזר אלינו לפני שאנחנו מנסים לעשות עם <code>response</code> פעולה כלשהי.</p>
<p>יש שני סוגים עיקריים של קוד א-סינכרוני שאנחנו ניתקל בהם בקוד javascript, יש את ה-callbacks הותיקים ואת ה-promises החדשים יותר. במאמר זה נסקור את שניהם.</p>
<h2 id="Async_callbacks">Async callbacks</h2>
<p>Async callbacks אלו פונקציות המועברות כפרמטר (ארגומנט) לפונקציה אחרת, כאשר אנחנו קוראים לפונקציה אחרת אשר מריצה קוד ברקע. כאשר הקוד שברקע סיים לרוץ, הוא קורא לאותן פונקציות callbacks על מנת לציין שהפעולה שהייתה ברקע הסתיימה או לציין שמשהו הסתיים.</p>
<p>שימוש ב-callbacks יחסית נחשב מיושן כעת, אבל אנחנו עדיין נראה שימוש רב שלהם ב-APIs ישנים אבל עדיין מאוד שימושיים.</p>
<p>דוגמא ל-async callback אפשר לראות בפרמטר השני של {{domxref("EventTarget.addEventListener", "addEventListener()")}} (כפי שראינו בפעולה למעלה):</p>
<pre class="brush: js notranslate">btn.addEventListener('click', () => {
alert('You clicked me!');
let pElem = document.createElement('p');
pElem.textContent = 'This is a newly-added paragraph.';
document.body.appendChild(pElem);
});</pre>
<p>הפרמטר הראשון הוא הסוג של האירוע שאנחנו רוצים להאזין להתרחשות שלו, והפרמטר השני הוא פונקציית callback שמופעלת ברגע שהאירוע מתרחש.</p>
<p>כאשר אנחנו מעבירים callback function כפרמטר לפונקציה אחרת, אנחנו רק מעבירים את הגדרת הפונקציה כפרמטר, כלומר ה-callback function לא מופעל באופן מיידי. הוא נקרא לאחר מכן (“called back”) באופן א-סינכרוני איפשהו בתוך הגוף של הפונקציה שקיבלה אותו כפרמטר. הפונקציה שקיבלה אותו כפרמטר היא האחראית להפעיל את ה-callback function כשנצטרך.</p>
<p>אנחנו יכולים לכתוב פונקציות משלנו שיכילו callback function באופן דיי פשוט יחסית. נסתכל על דוגמא שמעלה משאב באמצעות <a href="/en-US/docs/Web/API/XMLHttpRequest"><code>XMLHttpRequest</code> API</a> (<a href="https://mdn.github.io/learning-area/javascript/asynchronous/introducing/xhr-async-callback.html">דף האינטרנט</a>, ו- <a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/introducing/xhr-async-callback.html">קוד המקור</a>):</p>
<pre class="brush: js notranslate">function loadAsset(url, type, callback) {
let xhr = new XMLHttpRequest();
xhr.open('GET', url);
xhr.responseType = type;
xhr.onload = function() {
callback(xhr.response);
};
xhr.send();
}
function displayImage(blob) {
let objectURL = URL.createObjectURL(blob);
let image = document.createElement('img');
image.src = objectURL;
document.body.appendChild(image);
}
loadAsset('coffee.jpg', 'blob', displayImage);</pre>
<p>כאן יצרנו את פונקציית <code>()displayImage</code> שפשוט מקבלת blob שמועבר אליה ויוצרת לו URL באמצעות URL.createObjectURL(blob). לאחר מכן הפונקציה יוצרת אלמנט HTML מסוג <code>img</code>, משימה לו את הערך של ה-<code>src</code> לאותו URL שנוצר לנו ומשייכת את ה-image ל-body. </p>
<p>בנוסף, יצרנו פונקציה בשם <code>()loadAsset</code> שמקבלת כפרמטרים כתובת URL, סוג הקובץ וכן פונקציית callback (שימו לב שהשם שנתנו לפרמטר - <code>callback</code> - הוא לשם הנוחות בלבד וניתן לקרוא לפרמטר זה בכל שם). פונקציית <code>()displayImage</code> משתמשת ב-<code>XMLHttpRequest</code> (לרוב משתמשים בקיצור שלו - "XHR") על מנת להביא משאב מ-URL מסויים לפני שמעבירים את התגובה של אותה <code>XMLHttpRequest</code> לפונקציית callback שלנו - לפונקציית <code>()displayImage</code>.</p>
<p>במקרה הזה, פונקציית ה-callback שלנו מחכה ש-XHR יסיים להוריד את המשאב שהוא הביא (באמצעות שימוש במטפל אירוע מסוג <code><a href="/en-US/docs/Web/API/XMLHttpRequestEventTarget/onload">onload</a></code>), וזאת לפני שהיא תקבל את המשאב.</p>
<p>Callbacks הם מאוד ורסטיליים - לא רק שהם מאפשרים לנו לשלוט בסדר שבו פונקציות ירוצו ואיזה מידע יועבר ביניהן, הן גם מאפשרות לנו להעביר מידע לפונקציות שונות בהתאם לנסיבות. כך שאנחנו יכולים להריץ פעולות שונות על המשאב שהתקבל או התגובה שהתקבלה כמו <code>processJSON()</code>, <code>displayText()</code>, וכד׳. </p>
<p>שימו לב שלא כל ה-Callbacks הם א-סינכרוניים וחלקם הם סינכרוניים. כך לדוגמא, כאשר אנחנו משתמשים ב- {{jsxref("Array.prototype.forEach()")}} על מנת לעבור באמצעות לולאה על איברים במערך (<a href="https://mdn.github.io/learning-area/javascript/asynchronous/introducing/foreach.html">ראו כדף אינטרנט</a>, וכן <a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/introducing/foreach.html">את קוד המקור</a>):</p>
<pre class="brush: js notranslate">const gods = ['Apollo', 'Artemis', 'Ares', 'Zeus'];
gods.forEach(function (eachName, index){
console.log(index + '. ' + eachName);
});</pre>
<p>בדוגמא זו, אנחנו עוברים על מערך של Greek gods ומדפיסים את מספרי האינדקס והערכים לקונסולה. הפרמטר שאנחנו נותנים ל-<code>()forEach</code> הוא פונקציית callback, אשר בעצמו מקבל שני פרמטרים, שם הפריט במערך ומספר האינדקס. יחד עם זאת, היא לא מחכה לשום דבר, היא פשוט רצה באופן אוטומטי. </p>
<h2 id="Promises">Promises</h2>
<p>Promises אלו בעצם הסגנון החדש לקוד א-סינכרוני שאנחנו נראה שמבוצע בהם שימוש ב-Web APIs מודרניים. דוגמא טובה לכך היא <code><a href="/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch">fetch()</a></code> API, אשר הוא בעצם כמו גרסה מודרנית ויעילה יותר של {{domxref("XMLHttpRequest")}}. נסתכל על דוגמא מהמאמר שלנו בנושא <a href="/he/docs/Learn/JavaScript/Client-side_web_APIs/Fetching_data">הבאת מידע מהשרת</a> אשר תגיעו אליו בהמשך:</p>
<pre class="brush: js notranslate">fetch('products.json').then(function(response) {
return response.json();
}).then(function(json) {
products = json;
initialize();
}).catch(function(err) {
console.log('Fetch problem: ' + err.message);
});</pre>
<div class="blockIndicator note">
<p><strong>לתשומת לב</strong>: אתם יכולים למצוא את הגרסה הסופית ב- GitHub (<a href="https://github.com/mdn/learning-area/blob/master/javascript/apis/fetching-data/can-store-xhr/can-script.js">ראו כאן את קוד המקור</a>, וגם <a href="https://mdn.github.io/learning-area/javascript/apis/fetching-data/can-store-xhr/">כדף אינטרנט</a>).</p>
</div>
<p>כאן אנחנו רואים ש-<code>fetch</code><code>()</code> לוקח פרמטר אחד - את ה-URL של המשאב שנאחנו רוצים להביא מהרשת - והוא מחזיר <a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise">promise</a>. ה-promise היא בעצם אובייקט המייצג השלמה או כישלון של פעולת ה-שaysync. בצורה מסויימת, זו הדרך של הדפדפן להגיד ״אני מבטיח לחזור אליך עם תשובה ברגע שאוכל״. מכאן השם promise.</p>
<p>צריך להתרגל לרעיון הזה על ידי תרגול. זה מרגיש קצת מוזר בהתחלה, כמו החתול של שרדינגר - {{interwiki("wikipedia", "Schrödinger's cat")}}. אף אחת מהאפשרויות לא קרתה עדיין, אז פעולת ההבאה - פעולת ה-fetch, כרגע מחכה לתוצאה של פעולת הדפדפן - להשלמה שלה בעתיד. לאחר מכן שיש לנו שלושה קודי בלוק שמשורשרים לסוף <code>fetch()</code>:</p>
<ul>
<li>שני בלוקים של <code><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/then">then()</a></code>. שניהם מכילים callback function שתרוץ אם הפעולה שקדמה לה הצליחה, וכל callback מקבל כקלט, את התוצאה של הפעולה המוצלחת הקודמת, כך שאנחנו יכולים להמשיך ולעשות עם התוצאה משהו. כל <code>.then()</code> מחזיר הבטחה - promise נוספת, כלומר אנחנו יכולים לקשור כמה וכמה בלוקי קוד של <code>.then()</code> אחד לשני, כך שיהיוה הרבה פעולות א-סינכרוניות שירוצו בסדר מסויים, אחת אחרי השנייה.</li>
<li>בלוק הקוד של <code><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/catch">catch()</a></code> בסוף ירוץ אם אחד מהבלוקים של <code>.then()</code> ייכשל - בדרך דומה ל-<code><a href="/en-US/docs/Web/JavaScript/Reference/Statements/try...catch">try...catch</a></code> הסינכרוני. אובייקט שגיאה - error object - ייהפך לזמין בתוך ה-<code>catch()</code>, והוא יוכל לשמש עבור דיווח על סוג השגיאה שהתרחשה. שימו לב כי promises הסינכרוני לא עובד עם <code>try...catch</code>, למרות שהוא כן יעבוד עם <a href="/en-US/docs/Learn/JavaScript/Asynchronous/Async_await">async/await</a>, כפי שנראה בהמשך המאמר.</li>
</ul>
<div class="blockIndicator note">
<p><strong>לתשומת לב</strong>: אתם תלמדו עוד הרבה על promises בהמשך המודול הזה, אז אל דאגה אם לא הבנתם אותם עד הסוף. זוהי רק סקירה.</p>
</div>
<h3 id="The_event_queue">The event queue</h3>
<p>פעולות א-סינכרוניות כמו promises מושמות לתוך ה-<strong>event queue</strong>, אשר רץ לאחר שה-main thread סיים את העיבודים שלו, כך שהם לא יחסמו קוד JavaScript שבא אחריהם. הפעולות שב-promises יושלמו ברגע שיתאפשר, ויחזירו את התוצאה שלהן לסביבת הjavascript. Async operations like promises are put into an <strong>event queue</strong>, which runs after the main thread has finished processing so that they <em>do not block</em> subsequent JavaScript code from running. The queued operations will complete as soon as possible then return their results to the JavaScript environment.</p>
<h3 id="Promises_מול_callbacks">Promises מול callbacks</h3>
<p>ל-Promises יש קצת דמיון ל-callbacks הוותיקים. הם בעיקרון אבוייקט שהוחזר, אליו אנחנו מחברים פונקציות callbacks, ולא צריכים להעביר callbacks לתוך פונקציה.</p>
<p>יחד עם זאת, promises נוצרו במיוחד עבור טיפול בפעולת א-סינכרוניות, ויש להם הרבה יתרונות על ה-callbacks הוותיקים:</p>
<ul>
<li>ראשית, אנחנו יכולים לקשור מספר פעולות א-סינכרוניות ביחד באמצעות שימוש בכמה <code>.then()</code>, והעברה התוצאה של אחד כקלט של זה שאחריו. זה הרבה יותר קשה לביצוע עם callbacks, מה שבדרך מסתיים עם "pyramid of doom", אשר ידוע גם כ-ה</li>
<li>Promise callbacks תמיד ייקראו בסדר שבו הם מושמים ב- event queue.</li>
<li>Error טיפול ב- הוא הרבה יותר קל - כל השגיאות מטופלות על ידי בלוק <code>.catch()</code> אחד בסוף הבדלוק, ולא באמצעות טיפול בכל שלב של ה-פירמידה.</li>
<li>Avoid inversion control: unlike callbacks will lose full control of how the function will be executed when passing a callback to a third-party library. <a href="https://www.youtube.com/watch?v=bAlczbDUXx8">A great demonstration</a> by Stevie Jay.</li>
</ul>
<h2 id="ההתנהגות_של_קוד_א-סינכרוני">ההתנהגות של קוד א-סינכרוני</h2>
<p>בואו נעמיק בדוגמא שתסביר לנו יותר לעומק את ההתהנגות של קוד א-סינכרוני, שמראה מה יכול לקראת כשאנחנו לא בקיאים לגמי בסדר של הרצת הקוד וההבעיות שיש בניסיון לטפל בקוד א-סינכרוני כמו בקוד סינכרוני. הודמא הבא היא יחסית דומה למה שראינו בעבר. <a href="https://mdn.github.io/learning-area/javascript/asynchronous/introducing/async-sync.html">sכדף אינטרנט</a>, וגם <a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/introducing/async-sync.html">קוד המקור</a>). הבדל אחד הוא שכללנו מספר ביטויים של {{domxref("console.log()")}} על ממנת להמחיש את הסדר שאנחנו נחשוב שבו הקוד ירוץ</p>
<pre class="brush: js notranslate">console.log ('Starting');
let image;
fetch('coffee.jpg').then((response) => {
console.log('It worked :)')
return response.blob();
}).then((myBlob) => {
let objectURL = URL.createObjectURL(myBlob);
image = document.createElement('img');
image.src = objectURL;
document.body.appendChild(image);
}).catch((error) => {
console.log('There has been a problem with your fetch operation: ' + error.message);
});
console.log ('All done!');</pre>
<p>הדפדפן יתחיל להריץ את הקוד, הוא יראה את ה-<code>console.log()</code> הראשון ויריץ אותו. ולאחר מכן ייצור את המשתנה <code>image</code> .</p>
<p>הוא לאחר מכן ימשיך לשורה הבאה, ויתחיל להריץ את הבלוק קוד של <code>fetch()</code>, אבל מכיוון ש-<code>fetch()</code> מורץ באופן א-סינכרוני בלי חסימה, הדפדפן ימשיך לקוד שלאחר הקוד של ה-promise-related code, ולכן יגיע ל-<code>console.log()</code> האחרון ( <code>All done!</code>) ואותו יציג לקונסולה. ימשיך לרוץ</p>
<p>רק ברגע שהבלוק של ה-code>fetch() סיים לחלוטין לרוץ והביא תוצאה - result באמצעות הבלוקים של <code>.then()</code>, אנחנו נראה לבסוף את הההודעה שב-<code>console.log()</code> השני (<code>It worked ;)</code>). כך שההודעות הופיעו בסדר שונה ממה שאולי חשבתם:</p>
<ul>
<li>Starting</li>
<li>All done!</li>
<li>It worked :)</li>
</ul>
<p>אם זה מבלבל אתכם, הסתכלו על הדוגמא הבאה:</p>
<pre class="brush: js notranslate">console.log("registering click handler");
button.addEventListener('click', () => {
console.log("get click");
});
console.log("all done");</pre>
<p>זה מאוד דומה בהתנהגות - ה-<code>console.log()</code> הראשון והשלישי יציגו את ההודעות שלהן מיד, אבל ה-<code>console.log()</code> השני יהיה חסום להצגה עד אשר מישהו ילחץ על הכפתור. הדוגמא הקודמת פועלת בדרך דוה, למעט כך שבמקרה שההודעה השנייה חסומה בשרשרת ההבטחות המביאות משאב מסויים ומוצגת רק כאשר שרשרת ההבטטחות הושלמה, ולא כאשר המשתמש ילחץ על כפתור. .</p>
<p>בדוגמה של קוד פחות טריוויאלי, קוד מהסוג של הדוגמא הראשונה עלולה לגרום לבעיה - אינכם יכולים לכלול בלוק קוד אסינכרוני המחזיר תוצאה, עליה אתם מסתמכים בהמשך בבלוק קוד סינכרוני. אינכם כולים להבטיח שפונקציית ה-שaysync תחזור לפני שהדפדפן יעבד את חסימת האסינכרון.</p>
<p>על מנת לראות זאת בפעולה, נסו לעשות עותק מקומי של To see this in action, try taking a local copy of <a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/introducing/async-sync.html">הדוגמאו תשלנו</a>, ושנו את ה- <code>console.log()</code> שלישית כך:</p>
<pre class="brush: js notranslate">console.log ('All done! ' + image + 'displayed.');</pre>
<p>אתם אמורים לקבל שגיאה בקונסולה במקום ההודעה השלישית :</p>
<pre class="notranslate"><span class="message-body-wrapper"><span class="message-flex-body"><span class="devtools-monospace message-body">TypeError: image is undefined; can't access its "src" property</span></span></span></pre>
<p>זה מכיוון שבזמן שהדפדפן מנסה להריץ את ה-<code>console.log()</code> השלישית, הבלוק קוד של <code>fetch()</code> עדיין לא סיים לרות, כך שהמשתנה <code>image</code> לא ניתן לו ערך עדיין.</p>
<h2 id="למידה_עצמאית_פכו_את_הכל_ל-_async!">למידה עצמאית: פכו את הכל ל- async!</h2>
<p>על מנת לתקן את ה- <code>fetch()</code>, ולהפוך את שלושת -<code>console.log()</code> להיות מופעים בסדר הרצוי, אתם יכולים לעשות את ה-<code>console.log()</code> השלישי שירוץ גם הוא בצורה א-סינכרוני. את זה ניתן לעשות באמצעות העברה שלו לתוך <code>.then()</code> אחר, אשר משורשר לתוך הסוף של ה-<code>.then()</code> השני, או באמצעות פשוט העברה שלו לתוך ה-<code>.then()</code> השני. נסו לתקן זאת.</p>
<div class="blockIndicator note">
<p><strong>לתשומת לב</strong>: אם נתקעתם, אתם יכולים למצוא את התשובה <a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/introducing/async-sync-fixed.html">כאן</a> או כ <a href="https://mdn.github.io/learning-area/javascript/asynchronous/introducing/async-sync-fixed.html">דף אינטרנט</a> also). אתם גם יכולים למצוא עוד הרבה על promises במדריך שלנו בנושא <a href="/en-US/docs/Learn/JavaScript/Asynchronous/Promises">טיפול בפעולות א-סינכרוניות באמצעות Promises</a>, בהמשך המודול הזה.</p>
</div>
<h2 id="לסיכום">לסיכום</h2>
<p>במבנה הבסיסי שלה, JavaScript היא סינכרונית, שפה single-threaded,כך רק פעולה אחת יכולה להיות מעובדת בכל זמן נתון. יחד עם זאת, הדפדפנים הגדירו פונקציות ו-APIs שמאפשרים לנו לרשום פונקציות שלא ירוצו באופן סינכרוני, ובמקום זאת, יופעלו באופן א-סינכרוני כאשר אירוע מסויים מתרחש. זה אומר שאנחנו יכולים לתת לקוד שלנו לעשות דברים אחרים באותו הזמן, מבלי לחסום או לעצור את ה-main thread.</p>
<p>בין אם אנחנו רוצים להירץ קוד באופן סינכרוני או א-סינכרוני, זה תלוי במה שאנחנו מנסים לעשות.</p>
<p>יש פעמים שאנחנו נרצה שדברים יועלו ויתרחשו במיידי. לדוגמא, כאשר המתשמש מגדיר סגנון לאתר ואתם רוצים שהסגנון יוחל באופן מיידי.</p>
<p>אם אנחנו מריצים פעולה מסויימת שלוקח לה זמן, כמו לדוגמא גישה למאגר מידע ושימוש בתוצאות על מנת ליצור תבניות לדגומא, זה יהיה עדיף להעביר את הפעולה הזו מחוץ ל-main thread, כך שתתצבע באופן א-סינכרוני. עם הזמן, אתם תלמדו מתי זה היה הגיוני לבחור בטכניקה א-סינכרונית ולא בסינכורנית.</p>
<ul>
</ul>
<p>{{PreviousMenuNext("Learn/JavaScript/Asynchronous/Concepts", "Learn/JavaScript/Asynchronous/Timeouts_and_intervals", "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>
|