2015-12-10 1 views
3

Вот простейший пример возможного:Firebase.ServerValue.TIMESTAMP не синхронизируется между слушателями и клиентом, который фактически добавляет данных

var fb = new Firebase('https://xxxxxxxxxxx.firebaseio.com/test'); 

fb.limitToLast(1).on('child_added', function(snap) { 
    console.log('key', snap.key()); 
    console.log('val', snap.val()); 
}); 

fb.push({ 
    date_now: Firebase.ServerValue.TIMESTAMP 
}); 

Если открыть две вкладки с этим сценарием, тот, который на самом деле толкает данных получает local временная метка в обратном вызове child_added, а другая вкладка, которая только что прослушивается, получает соответствующий сервер. Насколько я понимаю, это делается для того, чтобы исключить круглые поездки и сэкономить пропускную способность.

Но для моей задачи это поведение неприемлемо. Как я могу его преодолеть?

Это console.log от толкателя:

key -K59mrvEUhTaoNIQQoA4 
val Object {date_now: 1449732570832} 

и слушателей (равно к данным сервера видели в приборной панели):

key -K59mrvEUhTaoNIQQoA4 
val Object {date_now: 1449732571759} 

ответ

5

Firebase пожары два местное событие для этой операции записи:

  1. сразу выстреливает child_added события с локальной меткой времени (с поправкой на ваш предполагаемое смещение к серверу)
  2. позже выстреливает child_changed события с фактическая метка времени, как указал сервер.

Таким образом, вы можете решить эту проблему путем прослушивания обоих событий:

var fb = new Firebase('https://xxxxxxxxxxx.firebaseio.com/test'); 

var query = fb.limitToLast(1); 
query.on('child_added', function(snap) { 
    console.log('key', snap.key()); 
    console.log('val', snap.val()); 
}); 
query.on('child_changed', function(snap) { 
    console.log('key', snap.key()); 
    console.log('val', snap.val()); 
}); 

fb.push({ 
    date_now: Firebase.ServerValue.TIMESTAMP 
}); 

В целом рекомендуется обрабатывать все child_* события, а не только child_added. Может быть больше причин, по которым сервер должен обновить или удалить значение, чтобы исправить локальное событие.

Если вы предпочитаете, имеющие обработчик одного обратного вызова/события, вы можете также слушать для value события:

var query = fb.limitToLast(1); 
query.on('value', function(snap) { 
    snap.forEach(function(child) { 
     console.log('key', child.key()); 
     console.log('val', child.val()); 
    }); 
}); 

Вы обратите внимание на использование forEach() в функции обратного вызова.

+0

Решает проблему «child_changed». Большое спасибо! – DEgorov

+0

Спасибо за объяснение Фрэнка! В этом случае я могу быть уверен, что значение, возвращаемое child_added, всегда будет отличаться от значения, возвращаемого child_changed? –

+1

Нет. Если нет перекоса часов, значение с сервера будет одинаковым. Это маловероятно, но может случиться. –

1

Для реального времени SDK это ожидаемое поведение. В конце концов, временная метка будет отображать правильное значение сервера. Но, если это не подходит вашим потребностям, вы можете использовать API REST.

function addTimestamp() { 
    fetch('https://<my-firebase-app>.firebaseio.com/test/.json', { 
    method: 'post', 
    headers: { 
     'Accept': 'application/json', 
     'Content-Type': 'application/json' 
    }, 
    body: JSON.stringify({ 
     '.sv': 'timestamp' // add a timestamp 
    }) 
    }); 
} 

Это не будет использовать локальную метку времени, так и в сочетании с Realtime SDK, каждый клиент будет иметь тот же метку времени первого обновления.

Смежные вопросы