Определение момента завершения вызовов вложенной базы данных firebase ref.on

У меня есть база данных, разработанная (примерно) следующим образом:

"users": {
  "userId1": {
    "challenges" {
     "challengeId1"=true,
     "challengeId2"=true
    }
  }, 
  "userId2": {
    "challenges" {
     "challengeId1"=true,
     "challengeId3"=true
    }
  }
  ...
  "userIdN": {...}
}          
"challenges": {
  "challengeId1": {
     "title" = "Title 1
    }
  },
  "challengeId2": {
     "title" = "Title 2
    }
  },
  "challengeId3": {
     "title" = "Title 3
    }
  }
}

В моем клиенте я делаю следующие вложенные вызовы:

const fetchChallengeList = (currUser) => {
  firebase.database().ref(`/users/${currUser.uid}/challenges`).on('child_added', snapshot => {
    firebase.database().ref(`/challenges/${snapshot.key}`).on('value', snapshotChall => {
      // Dispatch some stuff to UI
    });
  });
};

Обычно это отлично работает и синхронизирует все. Использование .on гарантирует, что каждый раз, когда добавляется новый вызов (пользователю: вызовы) или изменяется существующий вызов, тогда firebase обновляет пользовательский интерфейс.

Проблема в начальной загрузке. В идеале я хотел бы подождать, чтобы обновить пользовательский интерфейс (например, показать значок загрузки), пока СУЩЕСТВУЮЩИЕ задачи для пользователя изначально не закончат загрузку. В противном случае пользовательский интерфейс будет трястись и расширяться в течение 5-10 секунд. Поскольку все вызовы асинхронны и остаются открытыми, я понятия не имею, когда начальная установка завершила загрузку. Есть ли способ отследить это?

посмотрите JavaScript Promise и .then

Ronnie Royston 22.08.2018 18:23

Я знаком с Promise и .then, а также с Promise.all. Но я не уверен, к чему это меня привело. .on ('child_added') остается открытым и возвращает значение для каждой (дочерней) задачи. Вы априори не знаете, сколько его вернут. И даже если вы это сделали, вложенный обратный вызов firebase выполняется асинхронно и в разных областях. Вложенные обратные вызовы не знают друг о друге. Так что я не вижу возможности использовать Promise и .then.

Paul 23.08.2018 00:45
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
0
2
143
1

Ответы 1

Я бы создал способ показать / скрыть загрузчик что-то вроде

toggleLoader(display) => {
  // dont know the framework you are using 
  if (display) {
     $('.loader').show();
  } else {       
     $('.loader').hide();
  } 
}

Затем вы можете вызвать этот метод после загрузки задач.

const fetchChallengeList = (currUser) => {
  firebase.database().ref(`/users/${currUser.uid}/challenges`).on('child_added', snapshot => {
    firebase.database().ref(`/challenges/${snapshot.key}`).on('value', snapshotChall => {
      // Dispatch some stuff to UI
      toggleLoader(false);
    });
  });
};

Я бы также добавил некоторую обработку ошибок, чтобы выключить загрузчик в случае ошибки.

Вызовы firebase асинхронны. Если имеется более одного запроса, ваш ответ остановит загрузчик после получения первого запроса.

Paul 22.08.2018 18:06

Я понимаю, что это асинхронно, поэтому почему код находится в обратном вызове? firebase.googleblog.com/2016/01/…

Noel Kriegler 23.08.2018 07:56

Может я что-то упускаю. Но предположим, что у меня есть 3 проблемы. Это означает, что вложенный ref.on будет вызываться 3 отдельных раза, а затем обратный вызов, содержащий toggleLoader, будет вызываться 3 отдельных раза. Это означает, что при первом вызове пользовательский интерфейс будет отображаться, а 2-й и 3-й обратные вызовы покажут именно то, чего я пытаюсь избежать. (Я запустил код с консольным журналом для подтверждения). Но опять же, возможно, я неправильно понимаю, что вы предлагаете.

Paul 23.08.2018 11:47

Кроме того, я не могу использовать .then, как предполагает отправленная вами статья, потому что я вызываю .on, который, в отличие от .once, не возвращает Promise. Мне нужно использовать .on, чтобы изменения в задачах синхронизировались автоматически.

Paul 23.08.2018 12:11

@ Пол, я понимаю, о чем ты говоришь. Я думаю, что тогда получить желаемый результат непросто. Что вы могли бы сделать, так это получить все child_added из первого обратного вызова с помощью getChildrenCount() и увеличить счетчик на втором. Как только они сравняются, выключите загрузчик. В противном случае я бы предложил использовать fadeIns в вашем пользовательском интерфейсе, чтобы переход не был таким резким.

Noel Kriegler 28.08.2018 13:02

Другие вопросы по теме