לולאה שנתקעת ומדלגת פריטים
-
יש לי פונקצייה שאני מבצע עדכון הדפסה, אחרי שמדפיסים את כל הפריטים, אני עובר אחד אחד ומעדכן שהוא הודפס שלא יבוא בפעם הבאה להדפסה.
לא מצליח להבין למה הוא מעדכן לי חלק ונתקע, יש איזה דרך טובה. אני חייב עזרה, בניתי את זה כבר בארבע דרכים וכולן לא מוצלחות...
תודה רבהה. אני חייב בדחיפות לסדר את זה, יש לי יום התרמה במוצ"ש. ושוב תודה.export async function button108_click(event) { // sac = כמות של כל הפריטים if (sac>0) { let skip3=0, ms3; let hh3 =Number((sac/50).toFixed()); if (hh3>0) { ms3=Number((sac/50).toFixed()) +1 console.log((sac/50).toFixed()); let dd3=1 for (var i = 0; i < ms3; i++) { let results = await wixData.query("card").isNotEmpty("torem").ne("print","הודפס").skip(skip3).limit(50).find() let items = results.items; console.log(items); await items.map(obj => { console.log(obj); wixData.get("card", obj._id).then((item)=>{ item.print = "הודפס" return wixData.update("card", item) }) }) skip3 = skip3 +50 console.log(skip3); dd3=dd3+1 } } } Promise.all[( await anashim.map(item4 => { wixData.get('tormim', item4._id) .then((item6) => { console.log(item6); item6.print = "הודפס"; return wixData.update("tormim", item6); } ) .catch( (err) => { let errorMsg = err; } ); }) )] .then(()=>{ dard=undefined anashim=[] }) }
-
@אבי-203
נראה לי שהתכוונת לקוד כזה:
(אני מביא קוד ג'נרי לעדכון מערך בצורה אסינכרונית ואז לחכות שכל העדכונים יתבצעו)const myArray = await db.getSomeStuff(args); await Promise.all(myArray.map(item => { return item.update(params); }))
ולתרגם להקשר שלך:
await Promise.all(items.map(obj => { console.log(obj); return wixData.get('card', obj._id).then((item) => { item.print = 'הודפס'; return wixData.update('card', item); }); }));
Promise.all(anashim.map(item4 => { return wixData.get('tormim', item4._id) .then((item6) => { console.log(item6); item6.print = 'הודפס'; return wixData.update('tormim', item6); }) .catch((err) => { const errorMsg = err; }); }))
שים לב לשינויים בין קוד זה לקוד שלך. תדאג להבין את השינויים ולמה זה עובד. אחרת גם פעם הבא תסתבך.
כללים מהירים:
- שימוש ב-await נועד רק עבור אובייקט מסוג promise
- הפונקציה Promise.all מקבלת מערך של promise ומחזירה promise חדש שערכה העתידי הוא מערך של התוצאות של ה-promise-ים שהזנת לה.
- השימוש ב-map היא דרך קצרה לקבל מערך של כל הפרומיסים של כל העדכונים. זה שווה לקוד זה (שאומנם ארוך יותר אבל יותר קריא):
const myArray = await db.getSomeStuff(args); const promiseArray = []; for (const item of myArray) { const promise = item.update(params); promiseArray.push(promise); } await Promise.all(promiseArray);
אומנם קיימת בעיה בצורה זו:
Promise.all
מחזירה שגיאה מיד שאחד מהפריטים נכשלו מבלי לחכות לשאר הפרומיסים להסתיים.אפשר לפתור את זה על ידי שימוש בפונקציה יחסית חדשה: Promise.allSettled, או שאתה מוסיף
catch
ככה:const myArray = await db.getSomeStuff(args); await Promise.all(myArray.map(item => { return item.update(params).catch(err => err); }))
-
@yossiz תודדהה.
אני לא משתמש עד שאבין...
רואה את ההבדל בכיתוב לא מבין לגמרי.למשל למה בפעם השניה הזו
Promise.all(anashim.map(item4 => {
למה לא הוספת await
וגם איפה למשל אני מבין שהסתימו שני התהליכים ורק לאחר מכן תכניס הודעה הסתיים סגור חלון וכדו'.אולי החטא הקדמון שלא הבנתי את מהות promise
אגב אולי זה באמת הבעיה שאם היה אחד שגיאה הוא עוצר את הכל.
-
@אבי-203 אמר בלולאה שנתקעת ומדלגת פריטים:
אני לא משתמש עד שאבין...
למשל למה בפעם השניה הזו
Promise.all(anashim.map(item4 => {
למה לא הוספת awaitאתה צודק. אין סיבה להשתמש ב-Promise.all בלי לחכות לתוצאה.
וגם איפה למשל אני מבין שהסתימו שני התהליכים ורק לאחר מכן תכניס הודעה הסתיים סגור חלון וכדו'.
אחרי שחכית ל-promise.all.
await Promise.all(myArray.map(item => doSomeAsyncOperationOnItem())); console.log('הפעולה הסתיימה בהצלחה!');
אולי החטא הקדמון שלא הבנתי את מהות promise
לא "אולי", אלא ודאי . אבל לצערנו, אתה לא היחיד, יש הרבה אנשים (בלי לנקוב בשמות... ) שכותבים JS שנים ולא מבינים טוב מהות promise. אם תשקיע להבין את זה טוב, אני יכול לכתוב די בביטחון שההשקעה תחזיר את עצמה במהירות.
-
@yossiz
אני מעדכן שני רשימות. אז אני שם את זה אחרי השני הם אכן ממתינים אחד לשני? אני חושב ששוב לא הבנתי.await Promise.all(dard.map(item => { return wixData.get('card', item._id) .then((item2) => { console.log(item2); item2.print = 'הודפס'; return wixData.update('card', item2).catch(err => err) }) .catch((err) => { const errorMsg = err; }); })) await Promise.all(anashim.map(item4 => { return wixData.get('tormim', item4._id) .then((item6) => { console.log(item6); item6.print = 'הודפס'; return wixData.update('tormim', item6).catch(err => err) }) .catch((err) => { const errorMsg = err; }); })) .then(() => { console.log("הסתיים"); })
-
@אבי-203 הבנת טוב. הם אכן ממתינים אחד לשני.
יש לי עדיין כמה וכמה הצעות שיפור לקוד שלך:- לכאורה תוכל גם לעדכן את שתי הרשימות במקביל, אם אין תלויות בין אחד לשני.
- כדאי להשתמש במשתנים עם שמות תיאוריים, משתמש שהוא מערך, תן לו שם בלשון רבים. משתנה שהוא אובייקט מסוג
card
תקרא לוcard
ולא רקitem
סתמי, וכו' על זה הדרך. כן, אם יש כמה משתנים מסוגcard
אל תקרא להםcard1
,card2
אלא תן להם שמות לפי השימוש שלהם בקוד - לדוגמהnewCard
,updatedCard
וכן על זה הדרך. לא כדאי להשתמש בראשי תיבות, לא עולה כסף לכתוב במילואו. - יש שתי דרכים להתנהל עם פרומיסים: הדרך הישנה: שימוש ב-API של הפרומיסים, כלומר:
then
ו-catch
. הדרך החדשה: שמוש במילות המפתח -async
ו-await
.
(לדעתי) מומלץ להיות עקבי בצורת ההתנהלות ולא לקפוץ בין אחד לשני כל הזמן.
יש אומנם מקומות שבהם אין מנוס מלהשתמש ב-API של הפרומיסים, לדוגמה: אין תחליף לפונקציית Promise.all בתחביר ה-async/await
-י. ובמקרים אלו ההכרח לא יגונה. - אם הקוד שמעדכן את רשימת ה-
anashim
זהה לקוד שמעדכן את ה-cards
, ניתן לצרף אותם יחד לפונקציה ג'נרית לעדכון רשימה. - אאל"ט, אין צורך למשוך את האובייקט שוב מה-DB של WIX כדי לעדכן אותו, ניתן להשתמש באובייקט מהרשימה.
על פי כל הנ"ל, הייתי משכתב את הקוד שלך כך:
function updateItemPrinted (table, item) { item.print = 'הודפס'; return wixData.update(table, item); } await Promise.all([ ...cards.map((card) => updateItemPrinted('card', card)), ...anashim.map(torem => updateItemPrinted('tormim', torem)) ]); console.log('הסתיים');
קצר וקולע.
יפה, לא? -
@yossiz לא אתן לך על האחרונה לייק...
אבל עדין חסר לי.
אני מריץ את הלולאה על אובייקטים (anashim,dard) שנבנים בפונקצייה אחרת בפעולת ההורדה של הPDF.
ואז הפונקצייה הזו אמורה לעדכן במסד הנתונים לא באובייקט, למסד הנתונים קוראים tormim , card/וממה שכתבת נראה שהעדכון הוא באובייקט לא במסד הנתונים. אני טועה? או שמה שצבוע באדום זה ההדמייה שלך לשם מסד הנתונים
updateItemPrinted('card', card)),