从节点模块到 chrome 扩展的 WebSocket 连接在 Windows 10 中自动关闭

WebSocket connection from node module to chrome extension closing automatically in Windows 10

我使用 https://www.npmjs.com/package/ws npm 包在我的 npm 模块和我的 chrome 扩展之间进行通信。

连接正在打开,但将在几秒钟后关闭。

我研究了这个主题,我发现我应该在 webSocket 服务器和客户端之间来回发送消息以保持它的活动。

我每 2 秒处理一次此消息,但我的连接仍在关闭。

有趣的是,关闭事件仅在节点模块端触发,而 chrome 插件不会触发该事件。这是来自我的 chrome 扩展的代码:

function myPlugin() {
    myPlugin.prototype.socket = false;
    myPlugin.prototype.isConnected = false;
    myPlugin.prototype.port = false;
    myPlugin.prototype.pluginName = "Tab Reloader";

    myPlugin.prototype.init();
};

myPlugin.prototype = {
    initListeners: function () {
        chrome.browserAction.onClicked.addListener(function(tab) {
            if (!this.isConnected) {
                this.connectToServer();
            } else {
                this.disconnectFromServer();
            }
        }.bind(this));
    },

    setPort: function () {
        chrome.storage.sync.get(['port'], function(items) {
            this.port = items.port || '8001';
        }.bind(this));
    },

    getTabsToReload: function (callback) {
        var tabsToReload = [];

        chrome.storage.sync.get(['hostName'], function(items) {
            if (!items.hostName) {
                chrome.tabs.query({active: true}, function(tabs) {
                    tabs.forEach(function (tab) {
                        tabsToReload.push(tab);
                    });

                    callback(tabsToReload);
                });
            } else {
                chrome.tabs.query({}, function(tabs) {
                    tabs.forEach(function (tab) {
                        if (tab.url.indexOf(items.hostName) != -1) {
                            tabsToReload.push(tab);
                        }
                    });

                    callback(tabsToReload);
                });
            }
        }.bind(this));
    },

    initSocketListeners: function () {
        var fileExtIndex,
            fileExt,
            file;

        this.socket.onmessage = function (ev) {
            file = ev.data.toString();
            fileExtIndex = file.lastIndexOf('.') + 1;
            fileExt = file.slice(fileExtIndex),
            fileNameStandardize = file.replace(/\/g, '\/'),
            indexOfLastSeparator = fileNameStandardize.lastIndexOf('/') + 1,
            fileName = file.slice(indexOfLastSeparator);

            if (file != 'pong' && file.indexOf('connected to server!!!') == -1) {
                //do stuff
            } else {
                if (file == 'pong') {
                    this.isAlive = true;
                }
            }
        }.bind(this);

        this.socket.addEventListener('close', function (ev) {
            console.log('connection Closed')
            clearInterval(this.aliveInterval);
            chrome.browserAction.setIcon({
                path: {
                    "16": "img/icon_disabled_16.png",
                    "24": "img/icon_disabled_24.png",
                    "32": "img/icon_disabled_32.png"
                }
            });
            this.isConnected = false;
        }.bind(this));
    },

    connectToServer: function () {
        this.socket = new WebSocket("ws://localhost:" + this.port);

        this.socket.addEventListener('error', function (ev) {
            this.isConnected = false;
            alert('Error connecting to websocket server, make sure it\'s running and port ' + this.port + ' is not occupied by other process');
        }.bind(this));

        this.socket.addEventListener('open', function (ev) {
            this.isConnected = true;
            this.socket.send(this.pluginName + ' connected to server!!!');
            this.initSocketListeners();
            this.stayConnected();
            this.isAlive = true;
            this.aliveInterval = setInterval(function () {
                this.checkIfAlive();
            }.bind(this), 2500);

            this.getTabsToReload(function (tabsToReload) {
                tabsToReload.forEach(function (tab) {
                    chrome.tabs.update(tab.id, {url: tab.url});
                });
            });


            chrome.browserAction.setIcon({
                path: {
                    "16": "img/icon_active_16.png",
                    "24": "img/icon_active_24.png",
                    "32": "img/icon_active_32.png"
                }
            });
        }.bind(this));
    },

    disconnectFromServer: function () {
        this.socket.close();
    },

    stayConnected: function () {
        setTimeout(function () {
            this.socket.send('ping');

            if (this.isConnected) {
                this.stayConnected();
            }
        }.bind(this), 1000);
    },

    checkIfAlive: function () {
        this.isAlive = false;

        setTimeout(function () {
            console.log(this.isAlive)
            if (!this.isAlive) {
                console.log(this.isAlive)
                this.disconnectFromServer();
            }
        }.bind(this), 2000);
    },

    init: function () {
        this.setPort();
        this.initListeners();
    }
}

window.onload = new myPlugin();

这是我的节点模块代码:

    "use strict";

//var WebSocketServer = require('websocketserver');
//var WebSocketServer = require("nodejs-websocket")
var WebSocket = require('ws');

class MyModule {
    constructor(options) {
        this.options = options;
        this.server = false;
        this.pluginName = 'Some';
        this.isConnected = false;
        this.connection = false;

        this.init();

        return this.refreshTab.bind(this);
    }

    init() {
        var port = this.options ? this.options.port : false;
        this.server = new WebSocket.Server({port: port || 8001});

        this.server.on('connection', (websocket) => {
            console.log('Connection open');
            this.websocket = websocket;
            this.isConnected= true;

            this.initListeners();
        });
    }

    refreshTab(uploadedFiles) {
        if (this.isConnected) {
            if (Array.isArray(uploadedFiles)) {
                uploadedFiles.forEach(function (el) {
                    this.websocket.send(el.toString());
                }.bind(this));
            } else {
                this.websocket.send(uploadedFiles ? uploadedFiles.toString() : 'reload');
            }
        } else {
            console.log('You are not connected to server yet.');
        }
    }

    initListeners() {
        this.websocket.on('message', (message) => {
            if (message == 'ping') {
                this.websocket.send('pong');
            }
        });

        this.websocket.on('close', () => {
            this.isConnected = false;
            console.log(this.pluginName + ' connection is closed');
        });
    }
};

module.exports = MyModule;

感谢任何帮助, 提前致谢。

所以我的问题实际上是 manifest.json

"background": {
    "scripts": ["js/tab_reloader.js"],
    "persistent": false
}

"persistent" 设置为 false,它将我的背景页面转换为事件页面。并且事件页面在一段时间后从内存中卸载,这正在终止连接。在我将 "persistent" 设置为 true 后问题得到解决。