Promise.all + filter
-
נתון מערך של פרומיסים. (כאן זה פרומיסים מדומה, אבל זה יכול להיות fetch או קריאה לdb וכדומה) אני מעוניין לפלטר אותו עם פונקציית
filter
, ולהמתין לסים הפרומיסים + הפילטור.function promiseOk() { return new Promise((resolve, reject) => { setTimeout(() => { resolve(true); }, 1); }); } function promiseFailed() { return new Promise((resolve, reject) => { setTimeout(() => { resolve(false); }, 1); }); } const promisesList = [ promiseFailed(), promiseOk(), promiseFailed(), promiseOk() ]; // [Promise, Promise, Promise, Promise] const promisesStack = promisesList.filter(async (promise) => { const res = await promise; return res }); // [Promise, Promise, Promise, Promise] (async () => { const results = await Promise.all(promisesStack); console.log(results); // [false, true, false, true] })()
כפי שציינתי בהערות בקוד, אני מעביר מערך של פרומיסים (מערך של פונקציות async) אל Promise.all, שאליו אני ממתין עם await,
אך התוצאה היא מערך של 4 תוצאות, במקום 2 בלבד, כלומר גם הפרומיסים שמחזיריםfalse
עדיין נכללים - היינו שהפילטר לא פועל.
לעומת זאת כאשר אני ממתין למערך הפרומיסים, ורק אז מפלטר אותו, הוא מפולטר בהצלחה:(async () => { const results = await Promise.all(promisesList); console.log(results.filter((res) => res)); // [true, true] })()
תודה מראש.
-
@צדיק-תמים אתה מעביר לfilter פונקציה, אותה הוא מפעיל על כל פריט ולפי התוצאה הוא מחליט אם לכלול אותה בפלט.
הוא מצפה לקבל פונקציה שמחזירה ערך שהוא חיובי או שלילי, ככה:[true, false].filter(x => x);
אם אתה מסמן את הפונקציה כasync וכותב בה await, בעצם מה שחוזר הוא תמיד תמיד פרומייס:
typeof (x => Promise.resolve(x))() == 'object'; //true typeof (async x => await Promise.resolve(x))() == 'object'; //true
כלומר התוצאה תמיד חיובית.
אתה מצפה שfilter יפעיל await על התוצאה, אבל הוא לא. -
@dovid מעניין, כי
map
כן מתמודד בהצלחה עם פונקציה אסינכרונית:function promiseOk() { return new Promise((resolve, reject) => { setTimeout(() => { resolve(true); }, 1); }); } function promiseFailed() { return new Promise((resolve, reject) => { setTimeout(() => { resolve(false); }, 1); }); } const promisesList = [ promiseFailed(), promiseOk(), promiseFailed(), promiseOk() ]; // [Promise, Promise, Promise, Promise] const promisesStack = promisesList.map(async (promise) => { const res = await promise; return res + '4' }); // [Promise, Promise, Promise, Promise] (async () => { const results = await Promise.all(promisesStack); console.log(results); // ['false4', 'true4', 'false4', 'true4'] })()
הוא מחזיר מערך של פרומיסים, שאם אתה ממתין להם אתה מקבל את הערכים הממופים.
לכן הייתי בטוח שfilter
אמור לקבל גם... -
@צדיק-תמים גם
map
וגםfilter
לא "מכירים" בפרומיסים (כלומר לא מטפלים בצורה מיוחדת בפונקציה שמחזירה פרומיס, נראה לי שהסיבה פשוטה, כי פונקציות אלו היו קיימים לפני שהמושג "פרומיס" נכנס לשפה. גם אחרי שזה נכנס יש להסתפק אם זה יהיה נכון שהפוקציות יתנו לפרומיס טיפול מיוחד). אבל ההבדל פשוט,map
לוקח מה שאתה מחזיר ומכניס אותו למערך חדש. אבלfilter
מצפה לקבל ערך בוליאני, וכל ערך שהוא לא בוליאני מומר לבוליאני לפי הכללים של מה נקרא ערך truthy. מכיון שפרומיס הוא ערך truthy ה-filter
מחזיר חיובי עבור כל האברים של המערך. -
פוסט זה נמחק!