דילוג לתוכן
  • דף הבית
  • קטגוריות
  • פוסטים אחרונים
  • משתמשים
  • חיפוש
  • חוקי הפורום
כיווץ
תחומים

תחומים - פורום חרדי מקצועי

💡 רוצה לזכור קריאת שמע בזמן? לחץ כאן!
  1. דף הבית
  2. תכנות
  3. שגיאה באסינכרוניות (async-await)

שגיאה באסינכרוניות (async-await)

מתוזמן נעוץ נעול הועבר תכנות
13 פוסטים 3 כותבים 249 צפיות
  • מהישן לחדש
  • מהחדש לישן
  • הכי הרבה הצבעות
התחברו כדי לפרסם תגובה
נושא זה נמחק. רק משתמשים עם הרשאות מתאימות יוכלו לצפות בו.
  • צדיק תמיםצ מנותק
    צדיק תמיםצ מנותק
    צדיק תמים
    כתב ב נערך לאחרונה על ידי
    #1

    מדובר בקוד שאמור לתשאל את הAPI של קול חי מיוזיק, ולקבל נתונים על רשימת שידורים חיים נבחרים (אפשר גם לקבל בבת אחת את המידע על כולם, אבל אני העדפתי ככה מסיבות שונות).

    // מערך של מספרי שידורים נבחרים
    let listLive = [35, 2, 3, 5, 37, 7, 16, 15, 23, 8, 27];
    /**
     * קבלת מידע בפועל מהAPI
     * @returns מערך של נתוני הערוצים הנבחרים
     */
    async function getLiveData() {
        let arrayLiveInfo = listLive.map(function (indexLive) {
            let resData = await fetch(`https://kcm.fm/Home/LiveJ/${indexLive}`);
            let jsonData = await resData.json();
            return jsonData;
        });
        return arrayLiveInfo;
    }
    
    console.log(getLiveData());
    
    

    משום מה זה מחזיר שגיאה:
    d5e30ba0-25d2-4b29-8b09-668b6d5bf807-image.png
    ואני לא מבין למה, הרי בשורה 7 הצהרתי על הפונקציה כאסינכרונית...

    Don’t comment bad code — rewrite it." — Brian W. Kernighan and P. J. Plaugher"
    טיפים

    ח dovidD 2 תגובות תגובה אחרונה
    0
    • ח מנותק
      ח מנותק
      חוקר
      השיב לצדיק תמים ב נערך לאחרונה על ידי
      #2

      @צדיק-תמים
      עליך לעשות כך

      /**
       * קבלת מידע בפועל מהAPI
       * @returns מערך של נתוני הערוצים הנבחרים
       */
      async function getLiveData() {
          let arrayLiveInfo = await listLive.map(async function (indexLive) {
              let resData = await fetch(`https://kcm.fm/Home/LiveJ/${indexLive}`);
              let jsonData = await resData.json();
              return jsonData;
          });
          return arrayLiveInfo;
      }
       
      console.log(getLiveData());
      

      וההסבר הוא שאתה מעביר ל listLive.map פונקציה שתטפל בקריאות, ואת הפונקציה ההיא לא הגדרת כ async.
      ההגדרה של async אמורה להיות על הפונקציה עצמה שבתוכה שמים את await, לא מספיק להגדיר בסקופ שמעל.

      צדיק תמיםצ תגובה 1 תגובה אחרונה
      3
      • צדיק תמיםצ מנותק
        צדיק תמיםצ מנותק
        צדיק תמים
        השיב לחוקר ב נערך לאחרונה על ידי
        #3

        @חוקר ניסיתי גם את זה, אבל בצורה כזאת זה לא מספק את הנתונים... ניסית להריץ את הקוד שהבאת?

        Don’t comment bad code — rewrite it." — Brian W. Kernighan and P. J. Plaugher"
        טיפים

        ח תגובה 1 תגובה אחרונה
        0
        • ח מנותק
          ח מנותק
          חוקר
          השיב לצדיק תמים ב נערך לאחרונה על ידי
          #4

          @צדיק-תמים אמר בשגיאה באסינכרוניות (async-await):

          @חוקר ניסיתי גם את זה, אבל בצורה כזאת זה לא מספק את הנתונים... ניסית להריץ את הקוד שהבאת?

          ניסיתי להריץ אבל קיבלתי שגיאה שאין לי מערך listLive

          צדיק תמיםצ תגובה 1 תגובה אחרונה
          0
          • צדיק תמיםצ מנותק
            צדיק תמיםצ מנותק
            צדיק תמים
            השיב לחוקר ב נערך לאחרונה על ידי
            #5

            @חוקר משום מה השמטת אותו בקוד שהבאת כאן... אני הבאתי אותו בקוד בפוסט הראשון (שורה 2)

            Don’t comment bad code — rewrite it." — Brian W. Kernighan and P. J. Plaugher"
            טיפים

            תגובה 1 תגובה אחרונה
            0
            • ח מנותק
              ח מנותק
              חוקר
              כתב ב נערך לאחרונה על ידי חוקר
              #6
              //const fetch = require('node-fetch'); מיועד לריצה באמצעות nodejs
              let listLive = [35, 2, 3, 5, 37, 7, 16, 15, 23, 8, 27];
              async function getLiveData() {
                  let a = [];
                  for (let i in listLive) {
                      let listLiveElement = listLive[i];
                      let resData = await fetch(`https://kcm.fm/Home/LiveJ/${listLiveElement}`);
                      listLiveElement =  await resData.json();
                      a.push(listLiveElement)
                  }
                  return a;
              }
              
              getLiveData().then(x => {
                  console.log(x)
              })
              

              אני רואה שרק עם for זה עובד

              תגובה 1 תגובה אחרונה
              1
              • dovidD מנותק
                dovidD מנותק
                dovid ניהול
                השיב לצדיק תמים ב נערך לאחרונה על ידי dovid
                #7

                @צדיק-תמים await זה צורה יותר חמודה לעשות promise, אבל בסוף זה promise.
                פונקציה של async בעצם מחזירה promise, ולא את הערך הסופי.
                בשביל לגשת לערכים אתה צריך לעשות await על כל אחת מהתוצאות, או להשתמש בPromise.all שתודיע לך על סיום של כולם.

                מנטור אישי למתכנתים (ולא רק) – להתקדם לשלב הבא!

                בכל נושא אפשר ליצור קשר dovid@tchumim.com

                צדיק תמיםצ 2 תגובות תגובה אחרונה
                1
                • צדיק תמיםצ מנותק
                  צדיק תמיםצ מנותק
                  צדיק תמים
                  השיב לdovid ב נערך לאחרונה על ידי צדיק תמים
                  #8

                  @dovid אמר בשגיאה באסינכרוניות (async-await):

                  בשביל לגשת לערכים אתה צריך לעשות await על כל אחת מהתוצאות

                  כלומר? הרי בשורה 9 אני ממתין לAPI, ובשורה 10 אני ממתין לתשובה המלאה מהשרת...

                  Don’t comment bad code — rewrite it." — Brian W. Kernighan and P. J. Plaugher"
                  טיפים

                  dovidD תגובה 1 תגובה אחרונה
                  0
                  • dovidD מנותק
                    dovidD מנותק
                    dovid ניהול
                    השיב לצדיק תמים ב נערך לאחרונה על ידי dovid
                    #9

                    @צדיק-תמים אמר בשגיאה באסינכרוניות (async-await):

                    @dovid אמר בשגיאה באסינכרוניות (async-await):

                    בשביל לגשת לערכים אתה צריך לעשות await על כל אחת מהתוצאות

                    כלומר? הרי בשורה 9 אני ממתין לAPI, ובשורה 10 אני ממתין לתשובה המלאה מהשרת...

                    ממתין בתוך הפונקציה, הבעיה שכל פונקציה מסוג async מחזירה מיידית ערך של פרומיס לפני כל ההמתנות. ולכן מי שקורא לה צריך גם הוא לשים await קרי: המתן לכל ההמתנות שבתוך הפונקציה.

                    מנטור אישי למתכנתים (ולא רק) – להתקדם לשלב הבא!

                    בכל נושא אפשר ליצור קשר dovid@tchumim.com

                    צדיק תמיםצ תגובה 1 תגובה אחרונה
                    3
                    • צדיק תמיםצ מנותק
                      צדיק תמיםצ מנותק
                      צדיק תמים
                      השיב לdovid ב נערך לאחרונה על ידי צדיק תמים
                      #10

                      @dovid ולמה זה לא עובד עם map?

                      Don’t comment bad code — rewrite it." — Brian W. Kernighan and P. J. Plaugher"
                      טיפים

                      dovidD תגובה 1 תגובה אחרונה
                      0
                      • צדיק תמיםצ מנותק
                        צדיק תמיםצ מנותק
                        צדיק תמים
                        השיב לdovid ב נערך לאחרונה על ידי
                        #11

                        @dovid אמר בשגיאה באסינכרוניות (async-await):

                        או להשתמש בPromise.all שתודיע לך על סיום של כולם.

                        הסתכלתי עכשיו על הPromise.all כאן ואני רואה שצריך להעביר לזה מערך של ההבטחות.
                        איך אני מעביר? הרי הסקופ של הלולאה (שבתוכה ההבטחה עצמה) מתפוגג בכל ריצה, והסקופ של הפונקציה גם כן לא גלוי כלפי חוץ...

                        Don’t comment bad code — rewrite it." — Brian W. Kernighan and P. J. Plaugher"
                        טיפים

                        dovidD תגובה 1 תגובה אחרונה
                        0
                        • dovidD מנותק
                          dovidD מנותק
                          dovid ניהול
                          השיב לצדיק תמים ב נערך לאחרונה על ידי
                          #12

                          @צדיק-תמים לא אמרתי שלא עובד עם map. אמרתי שאתה חייב או לחכות לכל תוצאה, או לעשות Promise.all שממתין עבורך לכל תוצאה.
                          תריץ את הקוד הבא בקונסול
                          הוא ממחיש את התוצאה ההמיידית של פונקציה אסינכרונית, תתעלם מgetNumber שרק מחליפה את הגישה לfetch, ותראה מה הפלט שלה

                          function getNumber(value){
                              return new Promise((y,x) => setTimeout(_ => y(value * value), Math.random() * 4000));
                          }
                          
                          let listLive = [35, 2, 3, 5, 37, 7, 16, 15, 23, 8, 27];
                          
                          function getNumbersList(){
                              return listLive.map(async function(item){
                                  console.log("כעת אההממ רוצה להתחיל את עיבוד " + item);
                                  let result = await getNumber(item);
                                  console.log("כעת גמר עיבוד של " + item);
                                  return result;
                              });
                          }
                          
                          let results =  getNumbersList();
                          
                          for (let index = 0; index < results.length; index++) 
                              console.log(`תוצאה מס ${index}: ${results[index]}`);
                          
                          for (let index = 0; index < results.length; index++) 
                              console.log(`תוצאת המתנה מס ${index}: ${await results[index]} `);
                          

                          אתה תראה שראשית כל מודפסים כל ה"כעת אההממ רוצה להתחיל את עיבוד", ואז כבר הלולאה מגיעה לעבור על איברי המערך למרות שהם לא סיימו את פעולתם.
                          בקוד שלך השגיאה היחידה הייתה חוסר הasync בפונקציה של הmap כמו ש@חוקר תיקן אותך בהודעתו הראשונה
                          אלא שה

                           console.log(getLiveData());
                          

                          ידפיס מערך של [object Promise] כי א) הוא קורה לפני שהם סיימו את העיבוד, ב) הוא מקבל מערך של פרומיסים ולא מערך של תוצאותיהם.
                          שינוי השורה האחרונה לזה:

                          for(let y of getLiveData())
                               console.log(await y);
                          

                          יעשה את העבודה.

                          מנטור אישי למתכנתים (ולא רק) – להתקדם לשלב הבא!

                          בכל נושא אפשר ליצור קשר dovid@tchumim.com

                          תגובה 1 תגובה אחרונה
                          3
                          • dovidD מנותק
                            dovidD מנותק
                            dovid ניהול
                            השיב לצדיק תמים ב נערך לאחרונה על ידי
                            #13

                            @צדיק-תמים אמר בשגיאה באסינכרוניות (async-await):

                            @dovid אמר בשגיאה באסינכרוניות (async-await):

                            או להשתמש בPromise.all שתודיע לך על סיום של כולם.

                            הסתכלתי עכשיו על הPromise.all כאן ואני רואה שצריך להעביר לזה מערך של ההבטחות.
                            איך אני מעביר? הרי הסקופ של הלולאה (שבתוכה ההבטחה עצמה) מתפוגג בכל ריצה, והסקופ של הפונקציה גם כן לא גלוי כלפי חוץ...

                            זה מה שעד עכשיו לא הבנת, הgetLiveData() מחזיר מערך של הבטחות, כי הmap מתרגם כל מספר להבטחה על תוצאת אינטרנט.

                            מנטור אישי למתכנתים (ולא רק) – להתקדם לשלב הבא!

                            בכל נושא אפשר ליצור קשר dovid@tchumim.com

                            תגובה 1 תגובה אחרונה
                            2

                            בא תתחבר לדף היומי!
                            • התחברות

                            • אין לך חשבון עדיין? הרשמה

                            • התחברו או הירשמו כדי לחפש.
                            • פוסט ראשון
                              פוסט אחרון
                            0
                            • דף הבית
                            • קטגוריות
                            • פוסטים אחרונים
                            • משתמשים
                            • חיפוש
                            • חוקי הפורום