通过附加选项卡禁用PouchDB Live Sync

时间:2018-01-09 18:34:22

标签: synchronization pouchdb

PouchDB有known (unresolved) issue,当在同一浏览器的多个选项卡中实例化同一数据库时,它禁止同步。在我的测试中(在Chrome上使用同步网关的6.4.1),此问题的深度比the error which is thrown when a new tab尝试实例化新的同步过程要严重得多。

据我所知,每当新标签尝试实例化同一个同步过程的新实例时,PouchDB.sync也会禁用原始标签中发生的同步过程。

我不确定它是如何做到这一点的,因为其他进程是在一个单独的窗口中运行,但我注意到原始选项卡不再推送或拉动更改。此外,原始选项卡无法知道它已被禁用(因为它不会发出错误,更改或状态以指示这种情况)。而且,在尝试启动一个窗口(并遇到错误)之前,PouchDB中似乎没有办法检查另一个窗口是否已经有一个同步过程是运动。

因此,如果/当用户打开第二个标签页时,任何依赖{ live: true, retry: true }自动传播客户端更改的网络应用都可能会丢失数据。数据只会再次与服务器同步:

  1. 所有打开的标签均已关闭
  2. 打开一个新标签
  3. 在1和2之前不会发生注销/销毁事件。
  4. 这也会立即禁用服务器希望发送给客户端的任何更改。

    有没有人找到解决方法?

    通过检查同步是否已在运行,还是在禁用时重启?还是其他一些方法?否则,似乎实时同步不能在用户可能一次打开多个选项卡的生产环境中使用。避免此问题的唯一方法似乎是按需执行复制。

    解决:问题似乎来自浏览器的Origin Request Limits而不是PouchDB。如果有太多同步进程同时运行到同一地址,则浏览器会以不报告错误的方式禁用它们。感谢Dale Harvey helping identify the culprit

2 个答案:

答案 0 :(得分:0)

我发现同步问题的一种解决方法是使用Page Visibility API事件侦听器来打开/关闭同步。以下代码调整了另一个关于how to determine if the browser window is active的SO答案来停止和开始同步:

function VisibilityListener(callback=null) {

    var hidden = "hidden";

// Standards:
    if (hidden in document){
        document.addEventListener("visibilitychange", onchange);
    } else if ((hidden = "mozHidden") in document){
        document.addEventListener("mozvisibilitychange", onchange);
    } else if ((hidden = "webkitHidden") in document){
        document.addEventListener("webkitvisibilitychange", onchange);
    } else if ((hidden = "msHidden") in document){
        document.addEventListener("msvisibilitychange", onchange);
    }
// IE 9 and lower:
    else if ("onfocusin" in document){
        document.onfocusin = document.onfocusout = onchange;
    }
// All others:
    else {
        window.onpageshow = window.onpagehide = window.onfocus = window.onblur = onchange;
    }

// define function for change of status
    function onchange (evt) {
        var v = "visible"
        var h = "hidden"
        var evtMap = {
            focus:v, 
            focusin:v, 
            pageshow:v, 
            blur:h, 
            focusout:h, 
            pagehide:h
        }

        evt = evt || window.event;
        if (evt.type in evtMap){
            document.body.className = evtMap[evt.type];
        } else {
            document.body.className = this[hidden] ? "hidden" : "visible";
        }
        if (callback){
            callback(document.body.className)
        }
    }

// set the initial state (but only if browser supports the Page Visibility API)
    if ( document[hidden] !== undefined ){
        onchange({type: document[hidden] ? "blur" : "focus"});
    }

}

(function(){

    VisibilityListener(function(state){

        var sync_process = 'mydb_sync'
        var local_key = 'mydb'
        var remote_url = 'http://localhost:4984/mydb'
        var sync_options = { live: true, retry: true }

    // if window changes to visible state, start or restart sync
        if (state == 'visible'){
            window[sync_process] = PouchDB.sync(local_key, remote_url, sync_options)

    // if window changes to hidden state, stop sync
        } else if (state == 'hidden'){
            if (sync_process in window){
                window[sync_process].cancel()
            }
        }
    })

})();

答案 1 :(得分:0)

看看RxDB。它以多种方式扩展了PouchDB,它可能比您需要的更多,但它解决了多标签同步问题。