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

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

💡 רוצה לזכור קריאת שמע בזמן? לחץ כאן!
  1. דף הבית
  2. תכנות
  3. פניה אסינכרונית והמסתעף Angular TS

פניה אסינכרונית והמסתעף Angular TS

מתוזמן נעוץ נעול הועבר תכנות
22 פוסטים 5 כותבים 565 צפיות
  • מהישן לחדש
  • מהחדש לישן
  • הכי הרבה הצבעות
התחברו כדי לפרסם תגובה
נושא זה נמחק. רק משתמשים עם הרשאות מתאימות יוכלו לצפות בו.
  • yyyY מנותק
    yyyY מנותק
    yyy
    כתב ב נערך לאחרונה על ידי
    #1

    יש לי http//GetBooks - API שמחזיר מערך של אובייקטיםמסוג Book המייצגים ספרים.
    אני רוצה להציג את רשימת הספרים בקומפוננטה ShowBooks. בקומפוננטה זו יש חיווי חזותי האם קראתי את הספר או לא התלוי במשתנה hasReaded הנמצא בתוך Book.
    כל ספר אפשר לקרוא ולצורך כך יש קומפוננטה נפרדת BookReader.
    בסיום הקריאה אני מסמן "קראתי" והחיווי אמור להתעדכן אוטומטי כשאחזור ל-showBooks.

    המימוש מתבצע כך: בקונסטרקטור של ShowBooks נטען סרויס BooksSvc, אשר בקונסטרקטור שלו (של BooksSvc) מתבצעת פנייה אוטומטית לשרת ואת המערך שהיא מקבלת היא מציבה למערך בתוך הסרויס .
    כעת בהמשך הקונסטרקטור של showBooks פשוט מקבלים מהסרויס את רשימת הספרים העדכנית.
    showBooks

    this.books = BooksSvc.GetBooks();
    

    BookSvc

    GetBooksURL: string = "http:GetBooks";
       books: Book[] = [];
       constructor(private httpClient: HttpClient) {
         this.firstGetBooks().subscribe(b => {
          this.books =b;
         })
       }
       firstGetBooks(): Observable<Book[]> {
         return this.httpClient.get<Book[]>(this.GetBooksURL)
       }
       Getbooks() {
        return this.books
       }
    

    הבעיה היא שכשהקומפוננטה showBooks מבקשת את המערך מהסרוויס עדין לא תמיד המידע הגיע. הצלחתי לפתור את זה עם setTimeOut אבל זה פתרון גרוע לדעתי כי אתה לא יודע כמה זמן יקח למידע להגיע וזה או בזבוז זמן או שתיפול על פחות מידי זמן.
    איך אפשר לפתור את זה?

    תגובה 1 תגובה אחרונה
    0
    • י מנותק
      י מנותק
      יוסף בן שמעון
      כתב ב נערך לאחרונה על ידי
      #2
      פוסט זה נמחק!
      תגובה 1 תגובה אחרונה
      0
      • י מנותק
        י מנותק
        יוסף בן שמעון
        כתב ב נערך לאחרונה על ידי יוסף בן שמעון
        #3

        השורה הזו

        this.books = BooksSvc.GetBooks();
        

        אמורה להחזיר מערך שלא קיים.
        המתודה GetBooks לא אמורה להחזיר מערך, אלא פרומיס.
        כך אמור להיראות הסרביס

        GetBooksURL: string = "http:GetBooks";
           books: Promise<Book[]>;
           constructor(private httpClient: HttpClient) {
             this.GetBooks();
           }
        
           Getbooks() {
            return this.books = this.books || this.httpClient.get<Book[]>(this.GetBooksURL).toPromise();
           }
        

        והקומפוננטה תחכה לפרומיס כך

        this.books = await BooksSvc.GetBooks();
        
        yyyY תגובה 1 תגובה אחרונה
        1
        • W מנותק
          W מנותק
          WEB
          כתב ב נערך לאחרונה על ידי
          #4

          לא חייבים להפוך לפרומיס, observable הוא מצוין ויכול לעשות הרבה דברים שpromise לא יודע לעשות.
          כמו"כ למה לקרוא לhttp מתוך הconstructor של הservice? מקובל ליצור פונקציה בתוך הservice שהיא מחזירה את הobsevable של הקריאה. הconstructor משמש להזרקה של services אחרים לתוכו.
          אפשר לשים את הפונקציה שקוראת לhttp ישירות בתוך הhtml עם שימוש ב async pipe
          https://angular.io/guide/observables-in-angular#async-pipe

          yyyY תגובה 1 תגובה אחרונה
          1
          • yyyY מנותק
            yyyY מנותק
            yyy
            השיב ליוסף בן שמעון ב נערך לאחרונה על ידי
            #5

            @יוסף-בן-שמעון כתב בפניה אסינכרונית והמסתעף Angular TS:

            this.books = await BooksSvc.GetBooks();
            

            הכנסתי את השורה הזו ל-CTOR וקיבלתי שגיאה
            'await' expressions are only allowed within async functions and at the top levels of modules
            הכנסתי את הנ"ל לפונקציה נוספת בתוך showBooks

            async getBooks() {
             await  this.booksSvc.getBooks()
             }
            

            והשארתי את הקריאה מקונסטרקטור כך:

            this.books=  this.getBooks()
            

            כתוצאה מכך אני מקבל שגיאה

            Type 'Promise<void>' is missing the following properties from type 'Book[]': length, pop, push, concat, and 29 more.
            

            בקיצור לא הולך...

            W י 2 תגובות תגובה אחרונה
            0
            • yyyY מנותק
              yyyY מנותק
              yyy
              השיב לWEB ב נערך לאחרונה על ידי
              #6

              @WEB כתב בפניה אסינכרונית והמסתעף Angular TS:

              לא חייבים להפוך לפרומיס, observable הוא מצוין ויכול לעשות הרבה דברים שpromise לא יודע לעשות.

              אני משתמש ב-observable כדי לקבל מהשרת, אבל אני לא יודע להשתמש בו שרק כאשר יתאכלסו הנתונים מהשרת אל תוך הסרוויס, אז ישלף המידע.

              כמו"כ למה לקרוא לhttp מתוך הconstructor של הservice? מקובל ליצור פונקציה בתוך הservice שהיא מחזירה את הobsevable של הקריאה. הconstructor משמש להזרקה של services אחרים לתוכו.

              כי חשבתי שיהיה הגיוני פעם אחת לשלוף את המידע ולא כל פעם לבדוק האם המידע קיים או לא.

              תגובה 1 תגובה אחרונה
              0
              • W מנותק
                W מנותק
                WEB
                השיב לyyy ב נערך לאחרונה על ידי
                #7

                כתוצאה מכך אני מקבל שגיאה

                Type 'Promise<void>' is missing the following properties from type 'Book[]': length, pop, push, concat, and 29 more.
                

                בקיצור לא הולך...

                אתה מנסה להציב promise (פונקציית async מחזירה promise) לתוך משתנה מסוג []book. וודאי שתקבל שגיאה.

                אני משתמש ב-observable כדי לקבל מהשרת, אבל אני לא יודע להשתמש בו שרק כאשר יתאכלסו הנתונים מהשרת אל תוך הסרוויס, אז ישלף המידע.

                כי חשבתי שיהיה הגיוני פעם אחת לשלוף את המידע ולא כל פעם לבדוק האם המידע קיים או לא.

                בדיוק בשביל זה יש את הפונקציהsubscribe שרצה כאשר יש ערך מוחזר.
                כמו שכתבתי למעלה , אתה יכול להציב פונקציה שמחזירה observable בתוך הhtml עם שימוש ב async pipe
                כך

                {{getBooks() | async}}
                
                תגובה 1 תגובה אחרונה
                1
                • י מנותק
                  י מנותק
                  יוסף בן שמעון
                  כתב ב נערך לאחרונה על ידי
                  #8

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

                  תגובה 1 תגובה אחרונה
                  1
                  • י מנותק
                    י מנותק
                    יוסף בן שמעון
                    השיב לyyy ב נערך לאחרונה על ידי יוסף בן שמעון
                    #9

                    @yyy כתב בפניה אסינכרונית והמסתעף Angular TS:

                    בקיצור לא הולך...

                    באנגולר לא אמורים לעבוד עם הקונסטרקטור
                    הקומפוננטה עשויה להיראות כך:

                    export class showBooksComponent implements OnInit {
                        books: Book[];
                    
                        constructor(private BooksSvc: BooksSvc) { }
                    
                        async ngOnInit() {
                            this.books = await this.BooksSvc.GetBooks();
                        }
                    }
                    

                    זה יאפשר לך לבצע מניפולציות על המערך מתוך הקומפוננטה.
                    באופן כללי עדיף להמנע משימוש ב pipes כמו async ובבינדינג לפונקציות, זה מריץ את הפונקציה בכל בינדינג ודורש יותר משאבים.

                    yyyY תגובה 1 תגובה אחרונה
                    3
                    • yyyY מנותק
                      yyyY מנותק
                      yyy
                      השיב ליוסף בן שמעון ב נערך לאחרונה על ידי yyy
                      #10

                      @יוסף-בן-שמעון
                      עשיתי כדבריך:
                      זה הסרוויס

                      constructor(private httpClient: HttpClient) {
                        this.getBooks();
                      }
                      getBooks() {
                        return this.Books = this.Books || this.httpClient.get<Book[]>(this.GetBooksURL).toPromise();
                      }
                      

                      זה הקומפוננטה

                      constructor(
                         private BookSvc: BookSevice
                       ) {
                       }
                       async ngOnInit() {
                         this.books= await this.BookSvc.getBooks();  
                       }
                      

                      העניין שכעת לא מתבצעת בכלל פניה לשרת.

                      האמת (אני מניח שזה קשור לזה) שגם כך אשמח להכיר את הסינטקס של ה-return הנ"ל בשני דברים:
                      א. סימן ה"||" פירושו OR?
                      ב. מה המשמעות של קטע הקוד הזה
                      this.books = this.books
                      ?
                      תודה רבה.

                      י 2 תגובות תגובה אחרונה
                      0
                      • י מנותק
                        י מנותק
                        יוסף בן שמעון
                        השיב לyyy ב נערך לאחרונה על ידי
                        #11

                        @yyy כתב בפניה אסינכרונית והמסתעף Angular TS:

                        עשיתי כדבריך:

                        כמעט...
                        איך נראית השורה הזו בסרביס? כמו האופציה הראשונה או השניה?

                           books: Promise<Book[]>;
                           books: Promise<Book[]> = [];
                        
                        
                        yyyY תגובה 1 תגובה אחרונה
                        0
                        • י מנותק
                          י מנותק
                          יוסף בן שמעון
                          השיב לyyy ב נערך לאחרונה על ידי יוסף בן שמעון
                          #12

                          @yyy כתב בפניה אסינכרונית והמסתעף Angular TS:

                          האמת (אני מניח שזה קשור לזה) שגם כך אשמח להכיר את הסינטקס של ה-return הנ"ל בשני דברים:
                          א. סימן ה"||" פירושו OR?
                          ב. מה המשמעות של קטע הקוד הזה
                          this.books = this.books
                          ?

                          אכן, זה אופרטור OR.
                          כשאתה מבצע השמה למשתנה books אתה קודם כל בודק אם הוא כבר מאותחל, במידה והוא כבר אותחל אתה לא משנה בו כלום אלא מצביע עליו בחזרה, אם הוא עוד לא מאותחל והוא מחזיר undefined (שזה ערך false ב JS) אז אתה מאתחל אותו כפרומיס.
                          כך אתה מרויח שהפניה לשרת תתבצע רק פעם אחת בכל חיי האפליקציה, וכל מי שירצה לקבל את רשימת הספרים יקבל אותה מהפרומיס הזה

                          yyyY תגובה 1 תגובה אחרונה
                          1
                          • yyyY מנותק
                            yyyY מנותק
                            yyy
                            השיב ליוסף בן שמעון ב נערך לאחרונה על ידי
                            #13

                            @יוסף-בן-שמעון כתב בפניה אסינכרונית והמסתעף Angular TS:

                            books: Promise<Book[]>;
                            books: Promise<Book[]> = [];

                            לא כך ולא כך, אלא כך:

                            books:Books[] = [];
                            


                            זה:

                            books: Promise<Books[]>;
                            

                            מחזיר את השגיאה הזו
                            'books' has no initializer and is not definitely assigned in the constructor.
                            ואז אני מוסיף סימן ? ומקבל שגיאה ב-return

                            Type 'Promise<book[] | undefined>' is not assignable to type 'Promise<book[]>'.
                              Type book[] | undefined' is not assignable to type book[]'.
                                Type 'undefined' is not assignable to type book[]'.ts(2322)
                            

                            וזה:

                            books: Promise<Book[]> = [];
                            

                            מחזיר שגיאה:

                            Type 'never[]' is missing the following properties from type 'Promise<Book[]>': then, catch, finally, [Symbol.toStringTag]
                            
                            י תגובה 1 תגובה אחרונה
                            0
                            • י מנותק
                              י מנותק
                              יוסף בן שמעון
                              השיב לyyy ב נערך לאחרונה על ידי
                              #14

                              @yyy כתב בפניה אסינכרונית והמסתעף Angular TS:

                              זה:

                              books: Promise<Books[]>;
                              מחזיר את השגיאה הזו
                              'books' has no initializer and is not definitely assigned in the constructor.

                              אתה יכול לכתוב במקום סימן שאלה סימן קריאה, וזה ידלג על הבדיקה
                              או לאתחל את זה בקונסטקטור בלי האופרטור || ובמתודה getBooks רק להחזיר אותו בלי לעשות השמה

                              תגובה 1 תגובה אחרונה
                              1
                              • yyyY מנותק
                                yyyY מנותק
                                yyy
                                השיב ליוסף בן שמעון ב נערך לאחרונה על ידי
                                #15

                                @יוסף-בן-שמעון כתב בפניה אסינכרונית והמסתעף Angular TS:

                                כשאתה מבצע השמה למשתנה books אתה קודם כל בודק אם הוא כבר מאותחל,

                                זה נכון לגבי כל השמה, או שזה משהו ספציפי לפקודת return?

                                במידה והוא כבר אותחל אתה לא משנה בו כלום אלא מצביע עליו בחזרה,

                                למה פקודה כזו

                                return this.books || this.httpClient.get<Books []>(this.Getbooks URL).toPromise();
                                

                                לא מבצעת אותו דבר, הרי אם האובייקט אינו מאותחל זה יחזיר undefind כלומר false, וילך לפרומיס לאתחל את האובייקט, ואם זה כן מאותחל כלומר true שיחזיר אותו עצמו ולא יפנה לפרומייס?
                                בדקתי ואכן בסינטקס שלי הוא כן פונה כל פעם מחדש ואני רק שואל למה זה קורה.

                                א י 2 תגובות תגובה אחרונה
                                1
                                • yyyY מנותק
                                  yyyY מנותק
                                  yyy
                                  כתב ב נערך לאחרונה על ידי
                                  #16

                                  אגב ה-toPromise בהקשר זה הוא depricated

                                  תגובה 1 תגובה אחרונה
                                  1
                                  • א מנותק
                                    א מנותק
                                    אהרן
                                    השיב לyyy ב נערך לאחרונה על ידי
                                    #17

                                    @yyy כתב בפניה אסינכרונית והמסתעף Angular TS:

                                    למה פקודה כזו

                                    return this.books || this.httpClient.get<Books []>(this.Getbooks URL).toPromise();
                                    

                                    לא מבצעת אותו דבר, הרי אם האובייקט אינו מאותחל זה יחזיר undefind כלומר false, וילך לפרומיס לאתחל את האובייקט, ואם זה כן מאותחל כלומר true שיחזיר אותו עצמו ולא יפנה לפרומייס?
                                    בדקתי ואכן בסינטקס שלי הוא כן פונה כל פעם מחדש ואני רק שואל למה זה קורה.

                                    כי אתה אף פעם לא מאתחל אותו.

                                    תגובה 1 תגובה אחרונה
                                    2
                                    • י מנותק
                                      י מנותק
                                      יוסף בן שמעון
                                      השיב לyyy ב נערך לאחרונה על ידי
                                      #18

                                      @yyy כתב בפניה אסינכרונית והמסתעף Angular TS:

                                      זה נכון לגבי כל השמה, או שזה משהו ספציפי לפקודת return?

                                      כל השמה

                                      @yyy כתב בפניה אסינכרונית והמסתעף Angular TS:

                                      למה פקודה כזו

                                      returnthis.books || this.httpClient.get<Books []>(this.Getbooks URL).toPromise();
                                      לא מבצעת אותו דבר, הרי אם האובייקט אינו מאותחל זה יחזיר undefind כלומר false, וילך לפרומיס לאתחל את האובייקט, ואם זה כן מאותחל כלומר true שיחזיר אותו עצמו ולא יפנה לפרומייס?
                                      בדקתי ואכן בסינטקס שלי הוא כן פונה כל פעם מחדש ואני רק שואל למה זה קורה.

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

                                      getBooks() {
                                        if (this.books !== undefined) {
                                          return this.books;
                                        } else {
                                          this.books = this.httpClient.get<Book[]>(this.GetBooksURL).toPromise(); // <<<<<<<<<<<<<<<
                                          return this.books;
                                        }
                                      }
                                      

                                      אצלך דילגת על שורה 5, ובמקום זה עשית כך:

                                      getBooks() {
                                        if (this.books !== undefined) {
                                          return this.books;
                                        } else {
                                          return this.httpClient.get<Book[]>(this.GetBooksURL).toPromise();
                                        }
                                      }
                                      

                                      אז books מעולם לא אותחל

                                      yyyY תגובה 1 תגובה אחרונה
                                      2
                                      • yyyY מנותק
                                        yyyY מנותק
                                        yyy
                                        השיב ליוסף בן שמעון ב נערך לאחרונה על ידי
                                        #19

                                        @יוסף-בן-שמעון
                                        הטעות שלי היית שחשבתי שהתכוונת
                                        לזה

                                        return (this.Books = this.Books )|| this.httpClient.get<Book[]>(this.GetBooksURL).toPromise();
                                        

                                        ולא הבנתי מה ההצבה המוזרה באופרנד הראשון
                                        בשעה שהתכוונת באמת לזה:

                                        return this.Books = (this.Books || this.httpClient.get<Book[]>(this.GetBooksURL).toPromise());
                                        
                                        תגובה 1 תגובה אחרונה
                                        1
                                        • yyyY מנותק
                                          yyyY מנותק
                                          yyy
                                          כתב ב נערך לאחרונה על ידי yyy
                                          #20

                                          עכשיו ברשותכם שאלות:
                                          א.
                                          הפונקציה בסרוויס

                                          getBooks() {
                                            return this.Books = this.Books || this.httpClient.get<Book[]>(this.GetBooksURL).toPromise();
                                          } 
                                          

                                          מחזירה פרומיס
                                          אבל הפונקציה בקומפוננטה

                                          async ngOnInit() {
                                            this.books= await this.BookSvc.getBooks();
                                          

                                          מקבלת []Book ,
                                          השאלה היא האם הסיבה שמתבצעת ההמרה האוטומטית הזו, למרות שמדובר ב-TS, זה בגלל שיש async/await הוא מבין שהוא צריך לחלץ את הערך מהפרומיס?

                                          ב. אני מנסה לחבר את פרומיס זה לרעיון הכללי של פרומיס. אני ידעתי שהמצב של הפרומיס מוגדר ע"י הרצת resolve/reject, ואז פונים לthen או catch וכדו'. השאלה היא מי מריץ כאן מאחור את כל הפונקציות האלו הרי בקוד אני לא נוגע כאן ב-resolve then ודומיהם?

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

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

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

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