通常來說,對于大多數(shù)使用場景,頁面上只需要創(chuàng)建一個 cesium 的 viewer 就夠用了。
但是架不住,某些情況下,會需要多個 viewer 的存在。
了解 cesium 的童鞋應(yīng)該知道,一般情況下,一個 viewer 對應(yīng)著一個 webgl context,如果有多個就會存在多個 WebGLRenderingContext。
如果還不了解 WebGLRenderingContext 是什么的童鞋,建議去了解學習下 webgl 相關(guān)的知識,下面送上學習鏈接:https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext
對于大部分瀏覽器而言,都會對單個頁面同時激活的 WebGL contexts 有限制,可以參考下面的討論頁:
https://bugzilla.mozilla.org/show_bug.cgi?id=1421481
例如,在火狐瀏覽器的代碼里,就做了如下限制,對于 pc 而言,單個頁面同時激活的 WebGL contexts 不能超過 16 個。

所以,為了使我們的程序能夠保持正常的運行狀態(tài),我們必須要保證我們的頁面應(yīng)用嚴格的遵循這一原則。
我們可以寫一個小應(yīng)用, 進行測試,看一下,對于我們常用的瀏覽器,是否都會存在這個情況。
我們的應(yīng)用,分為左右兩側(cè),左側(cè)是一個一直存在的 viewer,右側(cè)是一個不斷銷毀和創(chuàng)建的 viewer 區(qū)域。
可以看到,當我們右側(cè)第17次創(chuàng)建 viewer 的時候,左側(cè)的 viewer 拋出異常錯誤。

打開控制臺,可以看到,瀏覽器提示激活了太多的 webgl contexts,最老的 context 將會丟失掉。

由此我們推測,雖然我們每次都調(diào)用了 viewer.destroy() 方法,來銷毀掉 viewer,并不等同于 webgl context 也被銷毀掉了。

那么,webgl context 有沒有提供 api 讓我們能夠手動銷毀掉創(chuàng)建出來的 context 呢?
經(jīng)過一番查找和研究,發(fā)現(xiàn)還是有的:https://developer.mozilla.org/en-US/docs/Web/API/WEBGL_lose_context

可以調(diào)用 WebGLRenderingContext getExtension 接口,拿到對應(yīng)的 extension,然后調(diào)用 loseContext 方法,能讓該 webgl context 失效掉。
這么說,其實我們 destory 掉 viewer 以后,cesium 源碼里并沒有調(diào)用上面這個方法,讓對應(yīng)的 webgl context 失效掉。
我們打開 vscode,對 cesium 的源碼進行全局檢索,檢索關(guān)鍵字 WEBGL_lose_context ,可以發(fā)現(xiàn)在我們的 cesium 1.85 的源碼里,并沒有找到相關(guān)的代碼。

所以,結(jié)論就很明顯了,正如我們前面所猜想的那樣,我們調(diào)用 destory 銷毀 viewer 的時候,當前 viewer 所用的 webgl context 并沒有被釋放掉,還是會占用資源。
所以,我們稍微對銷毀邏輯做一些優(yōu)化,改成下面這樣

我們在 destory 掉 viewer 以后,手動調(diào)用 gl.getExtension("WEBGL_lose_context").loseContext(); 方法。

可以看到,代碼像上面那樣改動了以后,在不斷銷毀、創(chuàng)建 viewer 的過程中,我們最開始被創(chuàng)建出來的 viewer 已經(jīng)不會丟失 webgl context 了,這樣就完美的解決了我們的問題。