jabbany / CommentCoreLibrary

Javascript Live Comment (Danmaku) Engine Implementation. JS弹幕模块核心,提供从基本骨架到高级弹幕的支持。
http://jabbany.github.io/CommentCoreLibrary/demo
MIT License
1.9k stars 304 forks source link

this.stage.removeChild(cmt.dom)报错 #85

Closed ellisfan closed 6 years ago

ellisfan commented 6 years ago
CommentCoreLibrary.js:1186 Uncaught DOMException: Failed to execute 'removeChild' on 'Node': The node to be removed is not a child of this node.
at CommentManager.finish (vendor/CommentCore/CommentCoreLibrary.js:1186:20)
at CssScrollComment.CoreComment.finish (vendor/CommentCore/CommentCoreLibrary.js:579:21)
at CommentManager.clear (vendor/CommentCore/CommentCoreLibrary.js:1077:29)
at HTMLDocument.<anonymous> 

问题就是我按下面的写法进行,在显示了大概20条左右的弹幕以后开始报错并且弹幕不显示,但是有插入DOM中。

先进行了初始化:

var startTime = 0, iVal = -1, playTime = 0;
// 初始化弹幕插件
var CM = new CommentManager(document.getElementById('my-comment-stage'));
CM.init();
// 先启用弹幕播放(之后可以停止)
CM.start();
// 开放 CM 对象到全局这样就可以在 console 终端里操控
window.CM = CM;

然后设置了一条初始的弹幕:

danmakuList.push({
    "mode":1,
    "text":"来自xx:大家好呀!~",
    "stime": 2000,
    "size": 25,
    "color":0xffffff
});

CM.load(danmakuList);

startTime = Date.now(); // 设定起始时间
if(iVal >= 0){
    clearInterval(iVal); // 如果之前就有定时器,把它停掉
}
//建立新的定时器
iVal = setInterval(function(){
    playTime = Date.now() - startTime; // 用起始时间和现在时间的差模拟播放
    CM.time(playTime); // 通报播放时间
    $('#runTime').html(playTime);
}, 100); // 模拟播放器每 100ms 通报播放时间

getMsg = setInterval(function () {
    getMessage(playTime);
},3000);

每三秒请求一次接口获取新的弹幕信息并插入弹幕池中:

var last_msg_number = "";
var msg_time = [3000, 4000, 5000, 6000, 7000, 8000];
var hasLastCheckReturned = false; // 标记之前检测是否已经完成,避免服务器过载
function getMessage(playTime){
    if(hasLastCheckReturned){
        return;
    }
    hasLastCheckReturned = true;
    $.ajax({
        url: "/?s=Sign/ActMsg/ajax_get_msg",
        data:{last_msg_number: last_msg_number,act_number:'{#$Think.get.act_number#}'},
        type:'get',
        dataType:'json',
        success:function(res){
            console.log(res);
            if(res && res.status == 0){
                hasLastCheckReturned = false;
                last_msg_number = res.data.msg_number;
                for(var i = 0; res.data.list.length > i; i++){
                    var stime = playTime + msg_time[Math.floor(Math.random()*msg_time.length)];
                    // console.log(stime);
                    var danmuObj = {
                        "mode":1,
                        "text":"来自"+res.data.list[i].wechat_name+":"+res.data.list[i].content,
                        "stime": stime,
                        "size": 25,
                        "color":0xffffff
                    };
                    console.log(danmuObj);
                    CM.insert(danmuObj);
                }
            }
        },
        error:function(){
            hasLastCheckReturned = false
        }
    });
}
jabbany commented 6 years ago

这个看着有可能是bug,应该是在你的代码哪里有调用CM.clear()? 但是看你给出的代码里面没有调用clear所以我也不知道在哪发生的问题。还有就是看起来好像用了一些模板系统?不知道这是不是也会影响。

at CommentManager.clear (vendor/CommentCore/CommentCoreLibrary.js:1077:29)
at HTMLDocument.<anonymous> 

比较好的办法是找一下你测试代码的时候里面有没有哪里调用了clear。一般来讲调用clear应该是没问题的因为只会清除runline里面的弹幕(而runline默认是“还在显示的弹幕”)。这个状态属于弹幕还在runline里面但是却不在舞台上(dom里)。这有可能是在什么时候弹幕被别的东西手动移除了dom(因为调用finish都是会解除绑定的)。

ellisfan commented 6 years ago

在监测DOM的时候发现,报错时DOM是未移除的,也没有其他代码将它们移除。 而且还在不断的新增新的弹幕DOM。

因为是大屏应用,所以弹幕的开关使用了键位监测,在另一个快捷键的监听中执行了clearInterval(getMsg);clearInterval(iVal);CM.stop();CM.clear();

ellisfan commented 6 years ago

@jabbany 是否与transform有关呢? 1515553602540

ellisfan commented 6 years ago

我现在临时解决办法是把

this.stage.removeChild(cmt.dom)

注释掉,然后写了个setInterval定时去清理DOM

jabbany commented 6 years ago

hmm,我还是没有足够的信息判断问题,不过我觉得可以采取下面的方式检查一下:

另外,如果只是临时想解决问题(虽然不推荐这样,因为我就没法找到bug了),可以把 this.stage.removeChild(cmt.dom) 改成:

if (cmt.dom.parentNode !== null) {
    cmt.dom.parentNode.removeChild(cmt.dom);
}

这样应该是OK的,不过这是一个比较掩盖症状的方法。。。

ellisfan commented 6 years ago

@jabbany 谢谢回复。因为是在前人的代码上新增需求,上线比较紧张,临时解决下。接下来会重新制作套新的模板。因为把弹幕这块单独拿出来就没有问题,估计还是和原本的代码冲突了。

coolicer commented 6 years ago

我用了一个其他人的弹幕库,如果没有弹幕,调了clear也有类似的错误。

jabbany commented 6 years ago

整理以下Issue,这个好久没有回应了就先关一下。 如果后续有类似问题,欢迎复活本issue(或者有新信息欢迎开新的issue)