זה נושא דיון מלווה לערך המקורי ב- https://www.tocode.co.il/bundles/html5-web-development/lessons/%D7%94%D7%91%D7%98%D7%97%D7%95%D7%AA-%D7%91-javascript
זה נושא דיון מלווה לערך המקורי ב- https://www.tocode.co.il/bundles/html5-web-development/lessons/%D7%94%D7%91%D7%98%D7%97%D7%95%D7%AA-%D7%91-javascript
לא הבנתי איפה בקוד הPromise מתחיל לרוץ - מרגע שהגדרתי לו את ה- Then ?
כמו כן ראיתי בתיעוד שניתן לשלוח שני פרמטרים לפונקציה then - הראשון פונקציה שמצליח , השני פונקציה שנכשל?
כמו כן ראיתי בתיעוד שהפונקציה then מחזירה בעצמה שוב Pramis כך שניתן שוב להגדיר אם הקודם הצליח אז שיעשה עוד פעולה - למה זה טוב ? למה לא יכולתי להכניס הכל בפעם הראשונה ?
אני חושב שהדוגמא כאן גם עוזרת להבין את העניין:
שים לב לכמה נקודות:
-
קודם כל Promise מקבל פונקציה. בהזדמנות הראשונה שיש ל JavaScript הוא יריץ את הפונקציה שנתת ל Promise. זאת הפונקציה שמתארת את התהליך העתידי שאתה רוצה לבצע. ה Promise הוא ״תוצאת חישוב עתידי״ ונותן דרך נחמדה לדבר על חישובים שעדיין לא הסתיימו.
-
מדויק - לפעמים אתה רוצה להגיד ״החישוב העתידי הזה, כשהוא יצליח תעשה X אבל אם הוא נכשל תעשה Y״. יש אגב גם אפשרויות נוספות להגדיר את זה למשל להוסיף קריאה ל catch על ההבטחה שחוזרת (בדומה לקריאה ל then).
-
מדויק שוב - והדבר מאפשר להשתמש בערך החישוב העתידי לצורך פעולה חדשה. הנה לדוגמא:
p = new Promise(function(resolve, reject) {
resolve(5);
});
p.then(function(val) {
return val * 2;
}).then(function(doubleValue) {
return new Promise(function(resolve, reject) {
resolve(doubleValue * 3);
});
}).then(function(result) {
console.log(result);
});
הקוד מדפיס 30 אפילו שבלוק ה then האמצעי מחזיר Promise. בצורה כזו אפשר לחבר מספר פעולות אסינכרוניות וכל אחת מחכה לזאת שלפניה ומשתמשת בתןצאה של זו שלפניה כדי להמשיך את החישוב.
דוגמא מהחיים: דפדפן פונה ל API כדי להזדהות, ולאחר מכן ממשיך ופונה לאותו API כדי לקבל מידע ואחרי שקיבל את המידע ממשיך בפניה שלישית ל API אחר כדי לקבל מידע נוסף שקשור לאותו מידע ראשוני. באמצעות שרשור Promises אפשר לייצג את כל הקריאות האלה כרצף של פעולות.
ראיתי באינטרנט דוגמאות שמשתמשים בפונקציה -subscripble במקום בהבטחה או asyc awit
מה זאת הפונקציה הזו תוכל לפרט ?
קישור? איפה ראית? תן דוגמא
קצת מתקשה להבין את היתרון של promise , מה רע למשל בקוד הזה ? שבמקום אחד מטפל בכל הפעולה עד סופה ?
var prompt = document.querySelector('#prompt');
var inputVal = document.querySelector('#prompt input');
var buttonStart = document.querySelector('#btn-start');
var btnGo = document.querySelector('#btn-go');
var result = document.querySelector('#result');
prompt.style.display = 'none';
buttonStart.addEventListener('click',function(){
inputVal.value = '';
prompt.style.display='block';
btnGo.addEventListener('click', function(){
var val = inputVal.value;
console.log(val.length);
if(val.length > 2){
prompt.style.display = 'none';
result.textContent = 'Hello ' + val;
}
});
});
הי מורדי,
תיקנתי את העימוד בקוד שלך (צריך להשתמש בסימן גרש הפוך שלוש פעמים כדי לקבל בלוק של קוד כאן). אתה יכול ללחוץ על העיפרון של ה Edit ולראות איך זה נראה מאחורה.
עכשיו לשאלה-
אי אפשר להבין Promise כשמסתכלים על חתיכת קוד אחת שעושה עבודה ספציפית, כי כמו שכתבת אתה יכול לטפל בכל העבודה באותו מקום וזה הכי נוח.
פרומיס עוזר במקרים שהעבודה באמת מופרדת. בוידאו נתתי את הדוגמא של Alert - אם אתה רוצה לייצר רכיב גנרי שיציג תיבת דיאלוג אז אתה לא יכול שאותו רכיב גנרי יעשה את כל העבודה, כי כל אחד ירצה להפעיל אותו בצורה קצת שונה ולהציג בתיבה תוכן אחר.
ייתרון אחר של Promise מגיע מהעובדה שהיום רוב הדפדפנים תומכים ב Promise בצורה מובנית וכוללים תחביר ספציפי לעבודה נוחה עם פרומיסים (הפונקציות async ו await). שווה לצפות בפרק הזה מקורס ES6 כדי לראות את זה:
היי,ינון
מה קורה לגבי REJECT ? אין הסבר כלשהו לגבי השימוש , האם תוכל להסביר קצת ? האם ניתן לשרשר PROMISES ?
ניסיתי את הקוד הנ"ל על מנת להוסיף הודעה כאשר התוכנית הסתיימה , תוכל להרחיב קצת את הוידאו הזה מעבר לבסיס ?
waitForUserInput().then(function(name){
result.textContent = "Hello "+name;
}).then(function(){
alert('working');
});
});
הי,
בוא ננסה אחד אחד-
אתה משתמש ב Promises כשיש לך קוד אסינכרוני שאתה רוצה להשתמש בו מכמה מקומות. אם זה היה קוד סינכרוני רגיל לא היתה לך בעיה - היית מוציא את הקוד הזה לפונקציה שלישית. אבל בקוד אסינכרוני יש בעיה, כי אנחנו לא יודעים מתי הוא יסתיים.
בוא נלך על רעיון פשוט של פונקציה שמחכה 3 שניות אחרי שהפעלת אותה ואז רושמת ל console. קוד הפונקציה נראה כך:
function waitThenWrite() {
setTimeout(function() { console.log('Done!'); }, 3000);
}
וזה כמובן עובד - אתה יכול לקרוא לפונקציה הזאת מכל מיני מקומות:
function main() {
waitThenWrite(); // now in 3 seconds a console.log will happen
}
אבל בניגוד לקוד סינכרוני רגיל כאן אם נוסיף שורת קוד אחרי waitThenWrite
היא בעצם תפעל לפני ההדפסה. כלומר הקוד הזה:
function main() {
waitThenWrite();
console.log('the end');
}
קודם ידפיס the end
ורק אז ידפיס את Done
מהפונקציה.
ועכשיו אנחנו מגיעים ל Promises - הפרומיס הוא הדרך הסטנדרטית לכתוב פונקציה שאפשר יהיה לקרוא לה ולחכות שהיא תסתיים.
בגירסת הפרומיס הקוד יראה כך:
function waitAndWriteAsPromise() {
return new Promise(function(resolve, reject) {
setTimeout(function() { console.log('Done'); resolve(); }, 3000)
});
}
function main() {
waitAndWriteAsPromise().then(function() {
console.log('the end');
});
}
ועכשיו סדר ההדפסות מסתדר וקודם תודפס המילה Done מהפרומיס ורק אחר כך יודפס הטקסט the end.
עכשיו לדברים המתקדמים:
- בסרט השני שקישרתי אני מראה שיש כתיב סטנדרטי בדפדפן לעבוד עם פרומיס שנקרא async/await. אותו הקוד בגירסא המודרנית נראה כך:
function waitAndWriteAsPromise() {
return new Promise(function(resolve, reject) {
setTimeout(function() { console.log('Done'); resolve(); }, 3000)
});
}
async function main() {
await waitAndWriteAsPromise();
console.log('-- the end');
}
זה עושה בדיוק את אותו הדבר, וגם הפונקציה waitAndWriteAsPromise לא השתנתה בכלל, אבל ה main עכשיו הרבה יותר נוח.
כמו ששמת לב הפונקציה השניה שאנחנו מעבירים לפרומיס נקראת reject. אם בתוך הפונקציה האסינכרונית אתה קורא לה (במקום ל resolve) אז ה await זורק Exception. זה מאפשר לנו לכתוב קוד ב main שנראה ככה:
async function main() {
try {
await waitAndWriteAsPromise();
} catch (err) {
console.log(err);
}
console.log('-- the end');
}
בסיטואציה כזאת המשתנה err יקבל את הערך ששלחת ל reject.
נקודה שלישית ואחרונה לבינתיים היא שאפשר גם להעביר ערך כשמפעילים את resolve, ואם עושים את זה הערך יוחזר בתור ערך ההחזר של הפונקציה האסינכרונית. זה מאפשר לכתוב קוד שנראה כך:
async function main() {
const x = await someAsyncCode();
console.log(x);
}
ועכשיו אנחנו נחכה עד שהפונקציה someAsyncCode תפעיל את resolve, והערך שהיא מעבירה ל resolve יישמר במשתנה x ורק אז יודפס על המסך.
זה אומר למשל שאתה יכול לכתוב קוד שנראה ככה:
async function getAnotherOne() {
pstatus.textContent = 'Fetching data for: ' + currentPerson;
const res = await fetch(`https://swapi.co/api/people/${currentPerson}/?format=json`);
const data = await res.json();
currentPerson += 1;
pstatus.textContent = 'done';
return data;
}
כי הפונקציה fetch מחזירה promise שה resolve שלו מחזיר תשובה מאתר אינטרנט מרוחק, והפונקציה json מחזירה פרומיס שה resolve שלו מחזיר אוביקט json .
כדאי גם לקרוא את הפוסט הזה שכתבתי באותו נושא:
וגם את זה:
תודה רבה ינון
שאלה נוספת ברשותך
ג’אווהסקריפט לא שפה אסינכרונית בבסיסה ?
אם כל await הפונקציה נחתכת וממתינה שפונקציה תסיים לעבוד אז הפעולה הופכת לסינכרוני וכל התוכנית ממתינה שאחת הפונקציות יסיימו ואז היא תמשיך , אני טועה ?
תוכל לתת דוגמא ממערכת שימושית שתוכל להמחיש את הצורך והפתרון שהדרך הזאת פותרת ?
תודה רבה
הי,
טועה- ה״חיתוך״ הזה לא עוצר את הריצה. זה בדיוק כמו להעביר Callback מכל הבחינות. אפשר לחשוב על זה כאילו יש מספר פונקציות וכל await בעצם מגדיר פונקציה חדשה שנקראת כשה Promise מסתיים.
כלומר זה:
doSomething().then(doSomethingElse);
שקול לזה:
await doSomething();
doSomethingElse();
לגבי דוגמא - רוב הפונקציות האסינכרוניות היום של ספריות ב JavaScript כבר עובדות ככה. תחשוב על קריאת Ajax - אז היום אתה כבר לא תכתוב קוד כזה:
$.get('/data', function(data) {
doSomethingWithTheData();
});
אלא קוד כזה:
const data = await $.get('/data');
doSomethingWithData();
כי jQuery כבר מחזירה Promise