2016-03-11 7 views
54

Mam szereg kluczy, które prowadzą do publikowania obiektów w mojej sieci społecznościowej, takich jak/post/id/(po informacji)Przyspieszenie pobierania postów dla mojej aplikacji w sieci społecznościowej za pomocą zapytania zamiast wielokrotnego obserwowania pojedynczego zdarzenia

Po załadowaniu postów załadowałem/postów/0, a następnie/postów/1 itd. Przy użyciu metody observeSingleEventOfType (.Value).

Używam lazyTableView do załadowania 30 na raz i jest dość powolny. Czy jest jakiś sposób mogę użyć jednej z metod kwerend lub inny sposób na przyspieszenie, nawet jeśli muszę do restrukturyzacji danych w moim drzewie JSON.

Pochodzę z Parse ponownie wdrażającej moją aplikację i do tej pory doświadczenie, które było całkiem dobre. Właśnie ta jedna rzecz utknąłem. Z góry dziękuję za pomoc!

EDIT:

func loadNext(i: Int) 
    { 
     // check if exhists 
     let ideaPostsRef = Firebase(url: "https://APPURL") 
     ideaPostsRef.childByAppendingPath(i.description).observeSingleEventOfType(.Value, withBlock: { 
      (snapshot) in 
      if i % 29 == 0 && i != 0 && !self.hitNull { return } 
      // false if nil 
      // true if not nil 
      if !(snapshot.value is NSNull) 
      { 
       let postJSON = snapshot.value as! [String: AnyObject] 
       print("GOT VALID \(postJSON)") 
       let post = IdeaPost(message: postJSON["message"] as! String, byUser: postJSON["user"] as! String, withId: i.description) 
       post.upvotes = postJSON["upvotes"] as! Int 
       self.ideaPostDataSource.append(post) 
       self.loadNext(i + 1) 
      } 
      else 
      { 
       // doesn't exhist 
       print("GOT NULL RETURNING AT \(i)") 
       self.doneLoading = true 
       self.hitNull = true 
       return 
      } 
     }) 

Ta funkcja rekurencyjna zasadniczo przebiega coraz wartość dla liczby klucza I z Firebase. Jeśli jest to NSNULL, wie, że jest to ostatni możliwy wpis do załadowania i nigdy więcej. Jeśli NSNULL nie zostanie trafiony, ale% 29 == 0, to zwraca jako podstawowy przypadek, więc tylko 30 wpisów jest ładowanych naraz (0 zindeksowane). Po ustawieniu metody doneLoading na true tableView.reloadData() jest wywoływane za pomocą obserwatora właściwości.

Oto próbka tego, co tablica ja ściągam wygląda jak

"ideaPosts" : [ { 
    "id" : 0, 
    "message" : "Test", 
    "upvotes" : 1, 
    "user" : "Anonymous" 
    }, { 
    "id" : 1, 
    "message" : "Test2", 
    "upvotes" : 1, 
    "user" : "Anonymous" 
    } ] 
+1

O wiele łatwiej będzie Ci pomóc, jeśli pokażesz nam swój kod zamiast go opisywać. Dodaj minimalny JSON (jako tekst, nie zrzut ekranu) i kod, aby odtworzyć problem w pytaniu i zobaczymy, jak można go poprawić. Przeczytaj więcej o [MCVE] (http://stackoverflow.com/help/mcve). –

+0

Edytowane w celu objaśnienia kodu –

Odpowiedz

78

Aktualizacja: teraz również obejmować tę kwestię w AskFirebase episode.

Ładowanie wielu elementów z Firebase nie musi być powolne, ponieważ możesz potokować żądania. Ale twój kod czyni to niemożliwym, co w rzeczywistości doprowadzi do nieoptymalnej wydajności.

W kodzie zażądasz elementu z serwera, poczekaj na powrót tego elementu, a następnie załaduj następny. W uproszczonym schematem sekwencji, który wygląda następująco:

Your app      Firebase 
          Database 

     -- request item 1 --> 
           S L 
           e o 
           r a 
           v d 
           e i 
     <- return item 1 -- r n 
            g 
     -- request item 2 --> 
           S L 
           e o 
           r a 
           v d 
           e i 
           r n 
     <- return item 2 --  g 
     -- request item 3 --> 
       . 
       . 
       . 
     -- request item 30--> 
           S L 
           e o 
           r a 
           v d 
           e i 
           r n 
            g 
     <- return item 30 -- 

W tym scenariuszu czekasz 30 razy swoim czasie obie strony + 30 razy więcej czasu potrzeba, aby załadować dane z dysku. Jeśli (dla uproszczenia) mówimy, że obie podróże trwają 1 sekundę, a załadowanie przedmiotu z dysku zajmuje jedną sekundę co najmniej do 30 * (1 + 1) = 60 sekund.

W zastosowaniach Firebase dostaniesz dużo lepszą wydajność, jeśli wysłać wszystkie żądania (lub przynajmniej wystarczającą liczbę z nich) za jednym zamachem:

Your app      Firebase 
          Database 

     -- request item 1 --> 
     -- request item 2 --> S L 
     -- request item 3 --> e o 
       .    r a 
       .    v d 
       .    e i 
     -- request item 30--> r n 
            g 
     <- return item 1 --  
     <- return item 2 --  
     <- return item 3 -- 
       . 
       . 
       . 
     <- return item 30 -- 

Jeśli ponownie przyjąć 1 i drugą podroż dookoła 1 sekunda ładowania, czekasz na 30 * 1 + 1 = 31 sekund.

Tak: wszystkie żądania są realizowane przez to samo połączenie. Biorąc pod uwagę, że jedyna różnica między get(1), get(2), get(3) i getAll([1,2,3]) jest trochę narzut dla ramek.

Skonfigurowałem jsbin to demonstrate the behavior. Model danych jest bardzo prosty, ale pokazuje różnicę.

function loadVideosSequential(videoIds) { 
    if (videoIds.length > 0) { 
    db.child('videos').child(videoIds[0]).once('value', snapshot => { 
     if (videoIds.length > 1) { 
     loadVideosSequential(videoIds.splice(1), callback) 
     } 
    }); 
    } 
} 

function loadVideosParallel(videoIds) { 
    Promise.all(
    videoIds.map(id => db.child('videos').child(id).once('value')) 
); 
} 

Dla porównania: kolejno załadunku 64 szt trwa 3,8 sekundy w moim systemie, podczas ładowania ich potokowego (jako klient Firebase ma natywnie) trwa 600ms. Dokładne liczby będą zależeć od połączenia (opóźnienie i przepustowość), ale wersja potokowa powinna zawsze być znacznie szybsza.

+10

Nice, Puf! Ponadto, przykuwające obietnice (jQuery.whenAll(), q.all() lub Promise.all()) mogą być bardzo przydatne, jeśli potrzebujesz załadować wszystkie elementy, ale mimo to chcesz je pobrać równolegle, zanim podejmiesz jakieś działanie. – Kato

+4

Cool. Nawet o tym nie myślałem, mimo że go używam. :-) –

+0

Czy brakuje mi czegoś? Wywołujesz loadVideosSequential dopiero po poprzednim "jednokrotnym" pobraniu migawki, podobnie jak to robi @ Big_Mac_24, ale z innym wywołaniem API. Czy możesz wyjaśnić różnicę? – Shirane85

Powiązane problemy