Ich habe eine Reihe von Schlüsseln, die dazu führen, dass Objekte für mein soziales Netzwerk wie so / posts / id / (Post-Info) veröffentlicht werden.
Wenn ich die Beiträge lade, lade ich / posts / 0 und dann / posts / 1 usw. mit der observeSingleEventOfType(.Value)
Methode.
Ich benutze a lazyTableView
, um 30 auf einmal zu laden und es ist ziemlich langsam. Gibt es eine Möglichkeit, eine der Abfragemethoden oder eine andere Methode zu verwenden, um sie schneller zu machen, selbst wenn ich die Daten in meinem JSON-Baum umstrukturieren muss?
Ich komme von Parse und implementiere meine App neu. Bisher war die Erfahrung recht gut. Nur diese eine Sache bin ich ein bisschen fest. Vielen Dank im Voraus für die Hilfe!
BEARBEITEN:
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
}
}
}
Diese rekursive Funktion wird im Wesentlichen ausgeführt, um den Wert für die Schlüsselnummer i von der Firebase abzurufen. Wenn es NSNULL ist, weiß es, dass dies der letzte mögliche Beitrag ist, der geladen wird, und wird es nie wieder tun. Wenn NSNULL nicht getroffen wird, aber i % 29 == 0
als Basisfall zurückgegeben wird, werden jeweils nur 30 Beiträge geladen (0 indiziert). Als ich festgelegt doneLoading
auf true
, tableView.reloadData()
wird als eine Eigenschaft Beobachter mit.
Hier ist ein Beispiel dafür, wie das Array, das ich abrufe, aussieht
"ideaPosts" : [ {
"id" : 0,
"message" : "Test",
"upvotes" : 1,
"user" : "Anonymous"
}, {
"id" : 1,
"message" : "Test2",
"upvotes" : 1,
"user" : "Anonymous"
} ]
Antworten:
Update: Wir behandeln diese Frage jetzt auch in einer AskFirebase-Episode .
Das Laden vieler Elemente aus Firebase muss nicht langsam sein, da Sie die Anforderungen weiterleiten können. Ihr Code macht dies jedoch unmöglich, was in der Tat zu einer suboptimalen Leistung führt.
In Ihrem Code fordern Sie ein Element vom Server an, warten auf die Rückgabe dieses Elements und laden dann das nächste. In einem vereinfachten Sequenzdiagramm, das wie folgt aussieht:
In diesem Szenario warten Sie auf das 30-fache Ihrer Hin- und Rückfahrt + das 30-fache der Zeit, die zum Laden der Daten von der Festplatte benötigt wird. Wenn wir der Einfachheit halber sagen, dass Roundtrips 1 Sekunde dauern und das Laden eines Elements von der Festplatte auch eine Sekunde dauert, die mindestens 30 * (1 + 1) = 60 Sekunden beträgt.
In Firebase-Anwendungen erzielen Sie eine viel bessere Leistung, wenn Sie alle Anforderungen (oder zumindest eine angemessene Anzahl davon) auf einmal senden:
Wenn wir erneut von einer Hin- und Rückfahrt von 1 Sekunde und einer Ladezeit von 1 Sekunde ausgehen, warten Sie auf 30 * 1 + 1 = 31 Sekunden.
Also: Alle Anfragen gehen über dieselbe Verbindung. In Anbetracht , dass der einzige Unterschied zwischen
get(1)
,get(2)
,get(3)
undgetAll([1,2,3])
ist ein gewisser Overhead für die Rahmen.Ich habe einen jsbin eingerichtet, um das Verhalten zu demonstrieren . Das Datenmodell ist sehr einfach, zeigt aber den Unterschied.
Zum Vergleich: Das sequentielle Laden von 64 Elementen auf meinem System dauert 3,8 Sekunden, während das Laden über eine Pipeline (wie der Firebase-Client nativ) 600 ms dauert. Die genauen Zahlen hängen von Ihrer Verbindung ab (Latenz und Bandbreite), aber die Pipeline-Version sollte immer deutlich schneller sein.
quelle