Ускорьте получение сообщений для моего приложения в социальной сети, используя запрос вместо того, чтобы неоднократно наблюдать одно событие
У меня есть массив ключей, которые приводят к публикации объектов для моей социальной сети, например, /posts/id/(информация о публикации)
Когда я загружаю посты, я загружаю /posts/0, а затем /posts/1 и т. Д., Используя метод наблюдаем единый_вентилятор (.Value).
Я использую lazyTableView для загрузки 30 одновременно, и это довольно медленно. Есть ли способ, которым я могу использовать один из методов запроса или другой способ сделать это быстрее, даже если мне придется реструктурировать данные в моем дереве JSON.
Я прихожу из Parse, повторно внедряю свое приложение, и пока опыт был довольно хорошим. Только одна вещь, на которой я немного застрял. Заранее спасибо за помощь!
РЕДАКТИРОВАТЬ:
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 не получен, но я% 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.
Загрузка многих элементов из Firebase не должна быть медленной, так как вы можете направлять запросы. Но ваш код делает это невозможным, что действительно приведет к неоптимальной производительности.
В своем коде вы запрашиваете элемент с сервера, ждете, пока этот элемент вернется, а затем загрузите следующий. В упрощенной диаграмме последовательности, которая выглядит следующим образом:
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 раз больше времени, необходимого для загрузки данных с диска. Если (для простоты) мы говорим, что круговые поездки занимают 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 мс. Точные значения будут зависеть от вашего соединения (задержка и пропускная способность), но конвейерная версия всегда должна быть значительно быстрее.