我正在构建一个简单的firebase应用程序。主要文本区域链接到Firebase上的条目。当用户键入内容时,我debounce
键入事件(300ms),然后在Firebase上进行更新。
每个.update
事件从服务器返回时都会触发一个onSnapshot
事件(这是Firebase的预期行为)。我的问题是,它会在用户键入内容时打扰他们。因为请求到达服务器的时间与返回服务器之间存在延迟。回来时,用户已经输入了更多文本,并且文本区域的内容与触发.update
时的文本区域不同。
这是我的代码和一个说明问题的jsFiddle:
var textareaElement = document.querySelector('textarea');
// Initialize Firebase
var config = {
apiKey: "XXX",
authDomain: "XXX",
projectId: "XXX",
};
firebase.initializeApp(config);
const db = firebase.firestore();
const doc = db.collection("notes").doc('XXX');
// This is debounced
const update = function(){
doc.update({
text: textareaElement.value,
updated_at: firebase.firestore.FieldValue.serverTimestamp()
})
}
// Update the server when we change the client
textareaElement.addEventListener('keyup', _.debounce(update, 300));
// Listen for changes from the server
doc.onSnapshot(function(doc){
textareaElement.value = doc.data().text
});
https://jsfiddle.net/x6h80keb/2(以正常速度输入,您会明白我的意思)
https://jsfiddle.net/x6h80keb/6/
我发现删除对serverTimestamp()
函数的调用很有帮助。看起来是造成请求延迟的原因。它使“错误”几乎不明显,但有时仍会在请求执行时间较长时发生。
我能想到的唯一解决方案是检测更新的发起者。每当触发onSnapshot
事件时,我们都可以查看doc
对象,并判断是从此客户端还是从另一个客户端进行了更改。但是显然没有这种功能。
有什么想法可以解决这个问题吗?
编辑:
我最终增加了反跳延迟。我没有等待300毫秒后更新,而是等待了几秒钟。这样,用户输入不会受到打扰。我还将在.update期间冻结文本区域。
答案 0 :(得分:1)
这是因为书面文档的内容可能与自文档更新以来用户输入的内容不同。
重新考虑以下代码:
doc.onSnapshot(function(doc){
textareaElement.value = doc.data().text
});
这将覆盖自触发反跳和自定义文档更新以来用户输入的内容。在具有高延迟的网络上,这尤其痛苦。
请考虑不在每次文档更改时重写整个文本区域,而是显示一个指示其键入同步状态的指示器。他们的打字是否同步?这就是用户需要知道的全部。您不需要定期覆盖它们的输入。