Ускорьте выборку сообщений для моего приложения социальной сети, используя запрос вместо многократного наблюдения за одним событием
у меня есть массив ключей, которые приводят к публикации объектов для моей социальной сети, таких как so / posts / id/(post info)
когда я загрузить я загрузить должностей /должностей/0 и /должностей/1 и т. д., Используя observeSingleEventOfType(.Значение) метод.
Я использую lazyTableView для загрузки 30 за раз, и это довольно медленно. Есть ли способ использовать один из методов запроса или другой способ сделать его быстрее, даже если мне нужно реструктурировать данные в моем дереве JSON.
Я исходя из разбора повторной реализации моего приложения и до сих пор опыт, как было довольно хорошо. Только одна вещь, на которой я немного застрял. Заранее спасибо за помощь!
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
}
}
}
эта рекурсивная функция по существу выполняет получение значения для ключевого числа i из firebase. Если это NSNULL он знает, что это последний пост для загрузки и никогда не повторится. Если NSNULL не попадает, но i % 29 == 0, то он возвращается как базовый случай, поэтому только 30 сообщений загружается одновременно (0 индексируется). Когда я установил doneLoading в true tableView.reloadData()
вызывается с помощью наблюдателя собственность.
вот пример того, что массив я получаю выглядит как
"ideaPosts" : [ {
"id" : 0,
"message" : "Test",
"upvotes" : 1,
"user" : "Anonymous"
}, {
"id" : 1,
"message" : "Test2",
"upvotes" : 1,
"user" : "Anonymous"
} ]
1 ответ:
обновление: теперь мы также рассмотрим этот вопрос в AskFirebase эпизод.
загрузка многие предметы из военнослужащих не должны быть медленными, так как вы можете конвейера запросов. Но ваш код делает это невозможным, что действительно приведет к неоптимальной производительности.
в вашем коде вы запрашиваете элемент с сервера, ждете, пока этот элемент вернется, а затем загрузите следующий. В упрощенной схеме последовательностей, которая выглядит например:
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 --
в этом случае ты ждал 30 раз туда и обратно раз + 30 раз время, необходимое для загрузки данных с диска. Если (для простоты) мы говорим, что roundtrips занимает 1 секунду, а загрузка элемента с диска также занимает одну секунду, что меньше всего до 30 * (1 + 1) = 60 секунд.
в приложениях Firebase вы получите гораздо лучшую производительность, если вы отправите все запросы (или, по крайней мере, разумное их количество) в одном вперед:
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 --
если мы снова предполагаем 1 второй круг и 1 секунду загрузки, вы ждете 30*1 + 1 = 31 секунда.
Итак: все запросы проходят через одно и то же соединение. Учитывая это, единственная разница между
get(1)
,get(2)
,get(3)
иgetAll([1,2,3])
некоторые накладные расходы для кадров.Я создал jsbin, чтобы продемонстрировать поведение. Модель данных очень проста, но она показывает разницу.
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')) ); }
для сравнения: последовательная загрузка 64 элементов занимает 3,8 секунды в моей системе, а загрузка их по конвейеру (как это делает клиент Firebase) занимает 600 мс. точные цифры будут зависеть от вашего соединения (задержка и пропускная способность), но конвейерная версия всегда должна быть значительно быстрее.