無論何時,記得做好代碼的清理工作


在看了一些關於HTML5 Audio API的資源后,一下子熱情高漲順勢寫了個音樂頻譜效果的作品來玩味,也就是上上篇博文里介紹的。今天在測試的時候發現三個問題處理得不是很好:

  1. 當歌曲正在播放的時候再選擇另一首,頁面頂部的標題沒有很好地更新
  2. 對於有些音頻文件,比如在上篇博文中提供的示例音樂里面,bbc_sherlock_openning.mp3這個文件在播放完畢后頻譜居然不會歸零!
  3. 另一個問題就是重點了,歌曲播放完了后后台代碼仍在不停地跑

結論

鑒於后面的內容是跟具體程序有關的(上上篇博文中介紹的Audio Visualizer),所以不知道源碼的你或許不太感興趣,於是把結論提前。

我想說的就是, 在JavaScript中遞歸使用了setTimeout或者setInterval,或者requestAnimationFrame(這個方法本身要求你遞歸使用),如果你的代碼有結束條件,最好在遞歸滿足結束條件后調用clearTimeout/clearInterval,cancleAnimationFrame來結束這些方法的運行。

就比如在問題三當中,我用的requestAnimationFrame來寫的動畫,當歌曲播放完畢,調用cancleAnimationFrame來清理之前設置的requestAnimationFrame以釋放內存。

下面是個關於取消requestAnimationFrame的簡單例子,來自css-tricks

 

var globalID;

function repeatOften() {
    $("<div />").appendTo("body");
    globalID = requestAnimationFrame(repeatOften);
}
$("#start").on("click", function() {
    globalID = requestAnimationFrame(repeatOften);
});
$("#stop").on("click", function() {
    cancelAnimationFrame(globalID);
});

 

Question 1

第一個問題是用戶體驗的問題,很好解決,所以對於頁面頂部的infobar作了如下調整:

  1. 程序開始顯示程序名稱"HTML5 Audio API showcase | An Audio Viusalizer"
  2. 用戶選擇文件或者拖拽文件到頁面后,顯示相應的后台操作,比如"文件上傳中。。。","文件解碼中。。。",etc.
  3. 途中出錯則顯示相應錯誤信息,比如"!解碼失敗",如果一切順利,則音樂開始播放並顯示當前播放的文件名,同時將文字淡下去,讓主題頻譜更好地呈現
  4. 歌曲順利結束,頂部信息恢復正常顯示,同時更新標題到最開始狀態,也就是顯示程序名
  5. 如果歌曲播放過程中用戶選擇了另外的文件,頂部信息恢復正常顯示並且轉到步驟2

Question 2

第二個問題,出乎我的意料,同時也想不通,不妨先來重現一下。

下圖便是播放bbc_sherlock_openning.mp3完畢后的畫面,程序就這樣停留在了這樣的一個畫面,有三根頻譜條沒有歸零。我硬盤里大部分歌曲都被我跑過了都沒問題,但才看了<神探夏洛克>的我執意要拿它的片頭曲來爽一把,然后就發現問題了。

我不認為是程序的問題,又無奈想不出這文件有什么問題,於是只能來硬的了。進行人工干預,在每首歌曲播放完畢后手動將從歌曲里面獲取的值也就是analyser設為0,這樣所有頻譜條都會沒有問題了。算是個笨拙的解決方法吧,因為沒有打到問題的根源。

具體代碼可以去下載最新版本的源碼查看。之前的代碼都有注釋,后來加的這些注釋不詳細,所以我自認為有點晦澀難懂。

Question 3

對於第三個問題,其實原因我知道,也知道如何解決,只是在創建程序時沒有好的方案來組織代碼避免其他問題。今天再次進行編碼時得到了解決。

解決之前,不妨先來看開發者工具中顯示的信息。

  1. 選擇文件進行播放
  2. F12打開高度工具,切到時間軸(Timeline)面板,選擇內存(memory)
  3. 點擊'記錄按鈕(Record)' 開始監視代碼執行過程中的內存及運行狀況

這是歌曲播放過程中,還看不出什么端倪。等待歌曲結束繼續觀測。

 

從上圖可以看出,即使歌曲結束,內存還是呈現規律地起伏,我們期望的是它穩定,並且上方的記錄數隨時間推進也在增加,說明后台代碼正在運行。

原因是代碼中使用了requestAnimationFrame設置動畫,並且每選擇一首歌后,都又會重新建立新的requestAnimationFrame來進行動畫,而前面的requestAnimationFrame沒有消失仍然存在,這樣一來,一首接一首的歌曲后可以預見到瀏覽器崩潰的情況。

解決方法也就是前面說的適時地調用cancelAnimationFrame來清理之前設置的動畫。

下圖展示了改進后的情況。可以看到,歌曲播放完畢后,記錄數停止了增加,說明后台代碼沒有再運行了,並且等待了一段時間后圖中的內存也處於穩定狀態,沒有起伏。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM