async ב - forEach
-
דבר ראשון אני לא מבין את הקוד שלי (מראשית האשכול), יש בו טעות.
אם עושים await אז הלולאה נתקעת והערך החוזר הוא לא promise אלא התוצאה, ממילא הPromise.all מיותר (זה עובד כי Promise.all עובד גם על רשימת ערכים). הקוד הנכון הוא או הסרה של הasync+await:var tasks = rows.map(function(row){ return updateRow(row); });
השארה של הasync+await והמרה של הPromise.all ללולאה רגילה על הtasks (שבעצם לא תכיל מערך פרומייז אלא מערך rows), גם תעבוד, אבל אני חושש שזה לא יעיל (תלוי באופן בו הawait עובד, אני הולך לבדוק את זה).
בנוגע לך @אהרן
א. setTimeout לא מחזיר את הערך של הפונקציה אלא מזהה מספרי שעוזר לבטל אותו בהמשך עם clearTimeout.
ב. בשביל ליצור פרומייז (שלוקח זמן) אתה חייב ליצור new Promise, ולדאוג שהקאלבק המוצלח יקרא לreslove כשהתוצאה (אם ישנה) מועברת כפרמטר.אז בשביל Promise.all תכתוב ככה:
var tasks = [1,2,3].map(function(row){ return new Promise((reslove) => setTimeout(() => reslove(row*2), Math.random()) ); }); Promise.all(tasks).then(function(newlist){ console.log(newlist) ; });
בשביל async+await ככה:
var values = [1,2,3].map(async function(row){ return await new Promise((reslove) => setTimeout(() => reslove(row*2), Math.random()) ); }); console.log(values) ;
-
טוב, בקשר לקוד השני האחרון, אני טעיתי שוב ולקח לי זמן להבין למה.
לפי דברי, הvalues אמור להכיל רשימה של מספרים - התוצאות. וניסיתי בקונסול, ולא, זה מחזיר רשימה של פרומייז...
קודם כל, למה אני חושב שזה חייב להחזיק מספרים ולא פרומייז? כי await Promise מחזיר תוצאה פרימיטיבית ולא פרומייז (ההשמה וכל מה שאחריה מתבצעת מאוחר מתי שהקאלבק נקרא, זה בעצם מאחורי הקלעים מומר לthen של פרומייז).
אבל כשעושים map ונותנים פונקציה מסוג async, אני מבין שכנראה במקום שעבור כל איבר יוכנס תוצאת הקאלבק, מאחורי הקלעים הפונקציה הזו הופכת לאובייקט פרומייז חדש, שעוטף את הפרומייז הפנימי.אקיצער, אין טעם לעשות async+await בפונקציית הmap. אלא יש להשתמש בפוקנציה רגיל שמחזירה פרומייז ואח"כ לעשות Promise.all.
-
@dovid אמר בasync ב - forEach:
אקיצער, אין טעם לעשות async+await בפונקציית הmap. אלא יש להשתמש בפוקנציה רגיל שמחזירה פרומייז ואח"כ לעשות Promise.all.
כלומר כך:
var values = [1,2,3,4,5,6,7,8,9].map(function(row){ return new Promise((reslove) => setTimeout(() => reslove(row*2), Math.random()*2000) ); }); Promise.all(values).then(function(newlist){ console.log(newlist) ; });
יש לך מושג אם הפונקציה שבתוך ה-map רצה על כל האיטרציות במקביל או שהם ממתינים אחת על השניה?
-
@אהרן אמר בasync ב - forEach:
יש לך מושג אם הפונקציה שבתוך ה-map רצה על כל האיטרציות במקביל או שהם ממתינים אחת על השניה?
זה
console.time('test1') var values = [1,2,3,4,5,6,7,8,9].map(function(row){ return new Promise((reslove) => { var rndom = Math.random()*2000; console.log(rndom) ; setTimeout(() => reslove(row*2), rndom) }); }); Promise.all(values).then(function(newlist){ console.timeEnd('test1') console.log(newlist); });
מוכיח שבמקביל.
-
מה אתם אומרים על זה:
function asyncMap(task) { return Promise.all( this.map(function(row){ return new Promise((reslove) => { task(row, reslove); }); }) ); } Array.prototype.asyncMap = asyncMap; [1,2,3,4,5,6,7,8,9].asyncMap( function(row, reslove){ setTimeout(() => reslove( row*2), Math.random()*3000); }) .then(function(newlist){ console.log(newlist); });
-
@אהרן אמר בasync ב - forEach:
@dovid אמר בasync ב - forEach:
להוסיף return
בשביל מה?
צודק, טעיתי בקריאת הקוד.
-
כשיש הרבה פונקציות משורשרות, פרומיס מאוד נוח, כיון שאפשר להריץ אותם שורה אחרי שורה באמצעות פונקצית then, וכך מקבלים מעין מפתח,
במקום לקרוא להם אחד מתוך השני.אבל בשביל זה
צריך פונקציה דומה שבכל איטרציה תריץ מערך של פונקציות שירוצו אחד אחרי השני,
שאפשר יהיה להריץ כך:[1,2,3,4,5,6,7,8,9].asyncMap( [func1, func2, func3] ) .then(function(newlist){ console.log(newlist); });
מה אומרים, אפשרי?