2014-07-21 88 views
0

我重新閱讀這篇文章在這裏:https://stackoverflow.com/a/24473888/1828637卸載器的實現是否正確?

,得到了關心,如果我正確地做事情。這是我如何卸載:

因此,我設置了每個窗口的東西。並在關機時卸載它們。 (我不會卸載窗口關閉,我還沒有發現需要,因爲當它關閉時,我添加到它的所有東西都與關閉[如我的突變觀察員])。

下面的所有代碼都是理論上的,突變的東西就是例子,所以可能有錯別字或者錯誤。我想知道,如果它背後的想法是適當的:

var unloadersOnShutdown = []; 
var unloadersOnClose = []; 

function startup() { 
     let DOMWindows = Services.wm.getEnumerator(null); 
     while (DOMWindows.hasMoreElements()) { 
      let aDOMWindow = DOMWindows.getNext(); 
      var worker = new winWorker(aDOMWindow); 
      unloadersOnShutdown.push({DOMWindow: aDOMWindow, fn: worker.destroy}); 
     } 
} 

function shutdown() { 
     Array.forEach.call(unloadersOnShutdown, function(obj) { 
      //should probably test if obj.DOMWindow exists/is open, but just put it in try-ctach 
      try { 
       obj.fn(); 
      } catch(ex) { 
       //window was probably closed 
       console.warn('on shutdown unlaoder:', ex); 
      } 
     }); 
} 

function winWorker(aDOMWindow) { 
    this.DOMWindow = aDOMWindow; 
    this.init(); 
} 

winWorker.prototype = { 
    init: function() { 
     this.gMutationObserver = new this.DOMWindow.MutationObserver(gMutationFunc.bind(this)); 
     this.myElement = this.DOMWindow.querySelector('#myXulEl'); 
     this.gMutationObserver.observe(this.myElement, gMutationConfig); 
     if (this.DOMWindow.gBrowser && this.DOMWindow.gBrowser.tabContainer) { 
      this.onTabSelectBinded = this.onTabSelect.bind(this); 
      this.gBrowser.tabContainer.addEventListener('TabSelect', this.onTabSelectBinded, false); 
     } 
    }, 
    destroy: function() { 
     this.gMutationObserver.disconnect(); 
     if (this.onTabSelectBinded) { 
      this.gBrowser.tabContainer.removeEventListener('TabSelect', this.onTabSelectBinded, false); 
     } 
    }, 
    onTabSelect: function() { 
     console.log('tab selected = ', thisDOMWindow.gBrowser.selectedTab); 
    } 
}; 

var windowListener = { 
    onOpenWindow: function (aXULWindow) {}, 
    onCloseWindow: function (aXULWindow) { 
     var DOMWindow = aXULWindow.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowInternal || Ci.nsIDOMWindow); 
     for (var i=0; i<unloadersOnClose.length; i++) { 
      if (unloadersOnClose.DOMWindow == DOMWindow) { 
       try { 
        unloadersOnClose.fn(); 
       } catch(ex) { 
        console.warn('on close unloader:', ex); 
       } 
       unloadersOnClose.splice(i, 1); 
       i--; 
      } 
     } 
    }, 
    onWindowTitleChange: function (aXULWindow, aNewTitle) {}, 
} 

我覺得有一個問題是我沒有使用與DOMWindow疲弱的引用,但我不知道。

回答

2

想法圍繞卸載器一般來說似乎是確定的,但非常有限(僅適用於Windows)。

缺乏實現。例如。有一個又大又肥的錯誤:

unloadersOnShutdown.push({DOMWindow: aDOMWindow, fn: worker.destroy}); 
// and 
obj.fn(); 
// or 
unloadersOnClose.fn(); 

這將調用winWorker.prototype.destroy與錯this

i++/i--循環也看起來,嗯... "interesting"?!

另外,請記住,可能存在細微的泄漏,所以您應該介意並測試Zombie compartments。 不僅窗口可能會泄漏部分附加組件(例如bootstrap.js),還可能通過在附加組件中保留引用來泄漏關閉的窗口。當然,這不僅僅是您需要關心的窗戶,還包括觀察員,其他類型的(XPCOM)聽衆等。

+0

重新錯誤的'this':如果他做了__(1)__'unloadersOnShutdown.push(worker)'(no object)then then shutdown did'unloadersOnShutdown [ I] .destroy()'?或__(2)__'unloadersOnShutdown.push({DOMWindow:aDOMWindow,fn:worker.destroy.bind(null)})'(bind null)?或__(3)__'var worker = new winWorker.bind(null,DOMWindow); unloaders.push(fn:worker.destroy);'(綁定在worker上)?大聲笑@維基鏈接到有趣的 – Blagoh

+2

@Blagoh 1)會工作。 2)不會工作'this === null'。應該是'worker.destroy.bind(worker)'。 3)沒有意義。綁定工作者是2)。 – nmaier

+0

哈哈你對i ++ i--意味着什麼? :P謝謝你。感謝那個殭屍頁面,我認爲它回答了我的問題,「何時運行卸載程序不限於windows」。 – Noitidart