我可以在一个小代码片段上减少我的问题。该代码动态创建一个 SC 播放器 iFrame 并显示就绪状态。如果已经有一个 iFrame,它会删除旧的并创建一个新的( JSFIDDLE 上的可运行示例):
var player;
var playerId;
var iframe;
var printReady=
function(data)
{
document.getElementById("status").innerHTML = "Ready";
};
function createSoundCloudIframe()
{
document.getElementById("status").innerHTML = "Player not ready";
var contentDiv = document.getElementById("content");
// Remove last Iframe
if(iframe != null){
player.unbind(SC.Widget.Events.READY);
contentDiv.removeChild(iframe);
}
// Create a new Iframe
iframe = document.createElement("IFRAME");
iframe.id = playerId + "ScId";
iframe.src = "http://w.soundcloud.com/player/?url=http%3A%2F%2Fapi.soundcloud.com%2Ftracks%2F41867062&show_artwork=true";
// Append Iframe
contentDiv.appendChild(iframe);
// Show ready status
player = SC.Widget(playerId + "ScId");
player.bind(SC.Widget.Events.READY, printReady);
playerId ++;
};
代码在第一次执行时运行良好。但是当你第二次尝试时,api.js的这个方法会抛出一个空指针异常(开发者控制台):
// Uncaught TypeError: Cannot read property 'parentWindow' of null
function s(a) {
return a.contentWindow || a.contentDocument.parentWindow
}
导致异常的方法是SC.Widget(iFrameId);
在我的情况下,这个问题无法通过SC.Widget(iFrameId).load(url, options);
功能和 iFrame 的隐藏来解决:我为 SC 小部件 api 编写了一个 google-web-toolkit 包装器,并在一个更大的项目中将此包装器与其他 gwt 媒体播放器包装器一起使用。在这个项目中,异常会以毫秒的延迟反复抛出,这会减慢一切。上面的代码片段只是对问题的纯 javascript 简化。
我真的需要一种解决方法,当 iFrame 被删除时,它会删除并清理 api.js 中的所有死引用!我正在寻找这样的解决方法一个月。