当弹出窗口关闭时,如何删除扩展弹出窗口的侦听器?

时间:2019-11-11 13:16:59

标签: javascript reactjs google-chrome-extension firefox-addon

我有一个使用react(旧版代码)构建的扩展,并且我一直在跟踪一个我最终陷入困境的错误,但是我无法修复。

单击扩展程序的图标(在浏览器栏中)时,将创建一个反应Component,并在其componentDidMount()中添加一个侦听器:

async componentDidMount(){
   ...
   // an object from the background is retrieved
   let background_object = this.props.getBackgroundObject();
   ...
   // code including await background_object.doSomething();
   ...
   // add event (eventemitter3 is used for the event management)
   background_object.event.on('onMusic', this.dance);
   ...
}

async dance() {
  this.setState({
    'music': true,
  })
}

但是,一旦Component消失,例如通过单击浏览器中的其他位置。我以为componentWillUnmount是我要寻找的东西,但是它从未被称为:

componentWillUnmount(){
  // this is never called!!!
  background_object.event.removeListener('onDance', this.dance);
}

问题是每次我打开(和关闭)扩展弹出窗口时,都会向background_object中添加一个新事件,因此dance()被多次调用(与我打开和关闭时一样多)。关闭弹出窗口。

目前,我使用的是once而不是on

async componentDidMount(){
   ...
   // an object from the background is retrieved
   let background_object = this.props.getBackgroundObject();
   ...
   // code including await background_object.doSomething();
   ...
   // add event (eventemitter3 is used for the event management)
   background_object.event.once('onMusic', this.dance);
   ...
}

async dance() {
 // add the event again in case onMusic is called again
 background_object.event.once('onMusic', this.dance);
 this.setState({
   'music': true,
 })
}

至少这样,它仅被调用一次。但是,我担心我的组件被多次创建并占用了我的浏览器中的内存。

如何确定该组件实际上已被销毁?如何检测何时关闭弹出窗口以删除事件?

1 个答案:

答案 0 :(得分:0)

为此可以使用chrome.runtime.onConnect(感谢@wOxxOm):

  1. 在React组件的构造函数中打开一个连接:
  constructor(props){
    super(props)
    this.state = {
      dance: false,
    }
    ...
    var port = this.xbrowser.runtime.connect();
    ...
  }

  1. 将事件添加到react组件的componentDidMount中。
async componentDidMount(){
   ...
   // an object from the background is retrieved
   let background_object = this.props.getBackgroundObject();

   ...
   // add event (eventemitter3 is used for the event management)
   background_object.event.on('onMusic', this.dance);
   ...
}

async dance() {
  this.setState({
    'music': true,
  })
}
  1. 后台的某个地方(例如background.js)监听与浏览器的连接,并在连接丢失时删除事件:
chrome.runtime.onConnect.addListener(function (externalPort) {
  externalPort.onDisconnect.addListener(function () {
     let background_object = this.props.getBackgroundObject();
     background_object.event.removeListener('onSend'); 
  })
})

在我的脑海中,这不是很优雅,但是可以解决问题。