Tengo una serie de claves que me llevan a publicar objetos para mi red social como / posts / id / (información de la publicación)
Cuando cargo las publicaciones, cargo / posts / 0 y luego / posts / 1, etc. usando el observeSingleEventOfType(.Value)
método.
Utilizo un lazyTableView
para cargar 30 a la vez y es bastante lento. ¿Hay alguna forma en que pueda usar uno de los métodos de consulta u otra forma de hacerlo más rápido incluso si tengo que reestructurar los datos en mi árbol JSON?
Vengo de Parse reimplementando mi aplicación y hasta ahora la experiencia ha sido bastante buena. Solo en esto estoy un poco atascado. ¡Gracias de antemano por la ayuda!
EDITAR:
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
}
}
}
Esta función recursiva esencialmente se ejecuta obteniendo el valor de la clave número i de firebase. Si es NSNULL, sabe que es la última publicación posible para cargar y nunca lo vuelve a hacer. Si NSNULL no se ve afectado, pero i % 29 == 0
luego regresa como caso base, por lo que solo se cargan 30 publicaciones a la vez (0 indexadas). Cuando me puse doneLoading
a true
, tableView.reloadData()
se llama usando un observador de la propiedad.
Aquí hay una muestra de cómo se ve la matriz que estoy recuperando
"ideaPosts" : [ {
"id" : 0,
"message" : "Test",
"upvotes" : 1,
"user" : "Anonymous"
}, {
"id" : 1,
"message" : "Test2",
"upvotes" : 1,
"user" : "Anonymous"
} ]
Respuestas:
Actualización: ahora también cubrimos esta pregunta en un episodio de AskFirebase .
La carga de muchos elementos desde Firebase no tiene por qué ser lenta, ya que puede canalizar las solicitudes. Pero su código lo hace imposible, lo que de hecho conducirá a un rendimiento subóptimo.
En su código, solicita un artículo del servidor, espera a que ese artículo regrese y luego carga el siguiente. En un diagrama de secuencia simplificado que se parece a:
En este escenario, está esperando 30 veces el tiempo de ida y vuelta + 30 veces el tiempo que lleva cargar los datos del disco. Si (en aras de la simplicidad) decimos que los viajes de ida y vuelta toman 1 segundo y cargar un elemento desde el disco también toma un segundo que al menos es 30 * (1 + 1) = 60 segundos.
En las aplicaciones de Firebase, obtendrá un rendimiento mucho mejor si envía todas las solicitudes (o al menos un número razonable de ellas) de una sola vez:
Si asumimos nuevamente un viaje de ida y vuelta de 1 segundo y 1 segundo de carga, está esperando 30 * 1 + 1 = 31 segundos.
Entonces: todas las solicitudes pasan por la misma conexión. Teniendo en cuenta que, la única diferencia entre
get(1)
,get(2)
,get(3)
ygetAll([1,2,3])
es algo de sobrecarga para los marcos.Configuré un jsbin para demostrar el comportamiento . El modelo de datos es muy simple, pero muestra la diferencia.
A modo de comparación: cargar secuencialmente 64 elementos toma 3.8 segundos en mi sistema, mientras que cargarlos en canalización (como lo hace el cliente de Firebase de forma nativa) toma 600ms. Los números exactos dependerán de su conexión (latencia y ancho de banda), pero la versión canalizada siempre debería ser significativamente más rápida.
fuente