Polymer 1.x + Firebase 2.x: данные Firebase не загружаются при первом рендере после входа в систему
При первой загрузке страницы после события входа пользователя в систему я хочу заполнить items
свойство с набором объектов, хранящихся в моем Firebase.
А добивается моего желаемого поведения.
<firebase-query
id="query"
...
path="users/[[user.uid]]/widgets"
data="{{items}}">
</firebase-query>
Б нет.
В<firebase-query
id="query"
...
path="widgets"
data="{{items}}">
</firebase-query>
При использовании B я ожидаю увидеть items
объект заполнен, но вместо items
объект является нулевым. Однако, если я обновлю браузер вручную (без выхода из системы), элемент будет работать так, как ожидается. Однако, если я выхожу из системы (затем обновляюсь при выходе из системы), проблема повторяется до тех пор, пока я снова не перезагрузлюсь. Если я только выйду из системы, то снова войду в систему, проблема не появится снова, я думаю, отчасти из- за того, что приложение не сбрасывается, как описано здесь.
Почему А работает? Но не Б? И какие изменения я должен внести в B, чтобы он заработал? (Потому что я хочу хранить widgets
от root/widgets/
путь и не нужно хранить эту деталь под users/...
дорожка.
Предыдущие неудачные попытки
Моя текущая (недоказанная) теория заключается в том, что в случае B (когда URL-адрес является постоянным / статическим, т.е. widgets/
) firebase-query
ввязывается в какое-то состояние гонки; и извлекает данные только после некоторого события жизненного цикла и не пытается повторно извлечь данные. С другой стороны, firebase-query
пытается повторно извлечь, когда путь динамически обновляется на основе привязки данных в path
атрибут (т.е. path="users/[[user.uid]]/widgets"
). Эта теория верна? Или есть какая-то другая причина? Нужно ли мне обязательно извлекать данные после какого-либо события? Если так, как я могу достигнуть всего этого?
Я попробовал следующие идеи без успеха.
Сuser: {
type: Object,
notify: true,
observer: '_userChanged',
},
_userChanged: function() {
this.$.query.path = 'widgets';
var items = this.$.query.ref.child('widgets');
this.set('items', items);
},
D <firebase-query
id="query"
...
path="[[path]]"
data="{{items}}">
</firebase-query>
<script>
...
properties: {
path: {
type: String,
value: function() {
return 'widgets';
},
}
},
...
</script>
Кроме того, на сайте о слабом полимере @ will-in-china сообщает:
У меня были проблемы с загрузкой данных в первый раз, я обнаружил, что если у меня нет более одной ссылки на один и тот же путь, я не получаю эту проблему.
Я не уверен, что это означает в этом контексте, так как в моем элементе (и приложении) есть только одна ссылка на путь path="widgets"
внутри firebase-query
элемент.
3 ответа
"При использовании A я ожидаю, что объект items будет заполнен, но вместо этого объект items будет нулевым. Однако если я обновлю браузер вручную (без выхода из системы), элемент будет работать так, как ожидается. Однако, если я выйду из системы (затем обновлю в то время как выход из системы), проблема появляется снова, пока я снова не перезагрузить."
Я вижу подобное поведение в моем приложении. В моем случае это связано с условиями гонки firebase-auth и firebase-query. В моем случае,
Когда я вхожу в систему, firebase-auth запускается одновременно / после firebase-запроса. В этом случае мой запрос отклонен из-за недопустимого разрешения - я запрашиваю его перед проверкой подлинности. Выписка из журнала ошибок:
"detail: Error: license_denied at /parent: у клиента нет разрешения на доступ к нужным данным. …, введите: "error", target: firebase-query .... firebase-query не повторяет попытку после завершения аутентификации. Я не знаю, если это ошибка.
Когда я обновляюсь после входа в систему, так как я уже аутентифицирован, запрос успешен.
Чтобы устранить эту проблему, я добавил обработчик ошибок, чтобы распечатать разрешения. Чтобы обойти эту проблему, я использую отключенное свойство. При первой загрузке страницы все запросы отключены. Только после успешной аутентификации я переключаю "отключено", и в этот момент запросы запускаются успешно.
signIn: function(){
var email = this.user.email;
var password = this.user.password;
this.$.auth.signInWithEmailAndPassword(email, password)
.then(function(response){
self.disabled = false;
// console.log('signin', response);
})
.catch(function(error){
console.log('auth-element:signIn error is', error.detail);
})
.then(function(){
// call other functions
});
},
handleError: function(error){
console.log('error message', error.detail.message);
},
<firebase-query
id = "query"
app-name="my-app"
path = "/shoeboxes"
data = "{{datauid}}"
on-error="handleError"
disabled="{{disabled}}">
</firebase-query>
Надеюсь это поможет. По сути, я обнаружил, что с полимером и огненной основой обещания лучше, чем автоматические привязки...
Я не думаю, что это ваша конкретная проблема, но она может быть похожа в том, что после входа в систему -> setNewRoute(nextPage) я не получил рендер и я изменил последующий шаблон ( Iron-Ajax) для запуска вручную, а не через наблюдателя.
loggon: function parseLogin(user, password) {
...
Parse.User.logIn(_user, _pass).then(function() {
page('/channels');
---
channels.render ...
_render: function() {
console.log('_render');
this.$.get_channlinq.headers = hdr;
//xhr params
var body = this._setQry(this.params.channelId);
this.$.get_channlinq.body = JSON.stringify(body);
//fetch , load , template will render
this.$.get_channlinq.generateRequest();
Я опаздываю, но я решаю это, используя условие dom-if, если пользователь мешает сделать запрос, если нет, пользователь аутентифицируется