简体   繁体   English

为什么事件被多次触发?

[英]Why event is triggered more than once?

I'm trying to add an event handler for an audio Javascript plugin using the SoundManager2. 我正在尝试使用SoundManager2为音频Javascript插件添加事件处理程序。 This is the function that plays a song and wait for the end of the song to execute the function again: 这是播放歌曲并等待歌曲结束以再次执行该功能的函数:

    function songPlay (newSrc) {

            htmlSound.src = newSrc;
            htmlSound.load();

            thisPlayer.find( ".total-position-scrubber" ).bind( "slide", function(event, ui) {
                htmlSound.currentTime = ui.value;
            });

            var currentArtist = currentRow.find(".total-artist").text();
            var currentTitle =  currentRow.find(".total-title").text();

            thisPlayer.find(".total-playing-artist").html(currentArtist);
            thisPlayer.find(".total-playing-title").html(currentTitle);

            htmlSound.addEventListener("timeupdate", function() {
                var newVolume = thisPlayer.find( ".total-volume-slider" ).slider("option", "value");
                htmlSound.volume = newVolume;

                var duration = htmlSound.duration * 1000;
                var durationTime = convertMilliseconds(duration, "mm:ss");
                thisPlayer.find(".total-song-duration").html(durationTime.clock );

                var position = htmlSound.currentTime * 1000;
                var positionTime = convertMilliseconds(position, "mm:ss");
                thisPlayer.find(".total-song-position").html(positionTime.clock );

                thisPlayer.find( ".total-position-scrubber" ).slider("option", "max", duration/1000);
                thisPlayer.find( ".total-position-scrubber" ).slider("option", "value", position/1000);

            });

            htmlSound.addEventListener("ended", function() {

                        // Find next checked song

                        currentRow = currentRow.nextAll(".can-play:first");

                        // If checked song exists after current song, load it
                        if(currentRow.length > 0)
                        {
                            var newSrc = currentRow.find("[src]").attr("src");
                            songPlay(newSrc);
                        }

                        else
                        {
                            // If no checked song exists after current song, load the first checked song in playlist
                            if(thisPlayer.find(".can-play").length > 0)
                            {
                                currentRow = thisPlayer.find(".can-play:first");
                                var newSrc = currentRow.find("[src]").attr("src");
                                songPlay(newSrc);
                            }
                            // Change pause button to play button
                            else
                            {
                                thisPlayer.find(".total-play").removeClass("total-pause");  
                            }

                        }
                        // If song is playing while next button is clicked play next song
                        if(thisPlayer.find(".total-pause").length > 0)
                        {
                            htmlSound.play();

                        }

            });

            thisPlayer.find(".total-row .total-not-playing").removeClass("total-playing");
            currentRow.find(".total-not-playing").addClass("total-playing");
        }

The only problem is that the "ended" event is triggered more than once every time that a song finishes. 唯一的问题是,每首歌曲结束时,都会多次触发“结束”事件。 After the "ended" event, the function is executed, and then the songPlay() function is executed again (this is the expected behavior), but then, the "ended" event is triggered again, before the song is finished, while it should wait for the end of the song. 在“结束”事件之后,将执行该函数,然后再次执行songPlay()函数(这是预期的行为),但是随后,在歌曲完成之前,将再次触发“结束”事件,同时应该等待歌曲的结尾。 Any idea of the cause of that behavior? 知道造成这种行为的原因吗?

The newSrc variable has always the right value. newSrc变量始终具有正确的值。

This is the "ended" event definition in SoundManager2: 这是SoundManager2中的“结束”事件定义:

_html5_events = {

  // HTML5 event-name-to-handler map
  ...
  ended: _html5_event(function() {

  var t = this._t;

  _s._wD(_h5+'ended: '+t.sID);
  t._onfinish();

 }),
 ...
}

Edit: 编辑:

Surprisingly, it worked just replacing the anonymous function with a declared function like this: 出乎意料的是,它仅用以下声明的函数替换匿名函数即可:

function eventListenerFunction() {

        // Find next checked song

        currentRow = currentRow.nextAll(".can-play:first");

        // If checked song exists after current song, load it
        if(currentRow.length > 0)
        {
            var newSrc = currentRow.find("[src]").attr("src");
            songPlay(newSrc);
        }

        else
        {
            // If no checked song exists after current song, load the first checked song in playlist
            if(thisPlayer.find(".can-play").length > 0)
            {
                currentRow = thisPlayer.find(".can-play:first");
                var newSrc = currentRow.find("[src]").attr("src");
                songPlay(newSrc);
            }
            // Change pause button to play button
            else
            {
                    thisPlayer.find(".total-play").removeClass("total-pause");  
            }

        }
        // If song is playing while next button is clicked play next song
        if(thisPlayer.find(".total-pause").length > 0)
        {
            htmlSound.play();

        }

});

function songPlay (newSrc) {

    htmlSound.src = newSrc;
    htmlSound.load();

    thisPlayer.find( ".total-position-scrubber" ).bind( "slide", function(event, ui) {
        htmlSound.currentTime = ui.value;
    });

    var currentArtist = currentRow.find(".total-artist").text();
    var currentTitle =  currentRow.find(".total-title").text();

    thisPlayer.find(".total-playing-artist").html(currentArtist);
    thisPlayer.find(".total-playing-title").html(currentTitle);

    htmlSound.addEventListener("timeupdate", function() {
        var newVolume = thisPlayer.find( ".total-volume-slider" ).slider("option", "value");
        htmlSound.volume = newVolume;

        var duration = htmlSound.duration * 1000;
        var durationTime = convertMilliseconds(duration, "mm:ss");
            thisPlayer.find(".total-song-duration").html(durationTime.clock );

        var position = htmlSound.currentTime * 1000;
        var positionTime = convertMilliseconds(position, "mm:ss");
        thisPlayer.find(".total-song-position").html(positionTime.clock );

        thisPlayer.find( ".total-position-scrubber" ).slider("option", "max", duration/1000);
        thisPlayer.find( ".total-position-scrubber" ).slider("option", "value", position/1000);

    });

    htmlSound.addEventListener("ended", eventListenerFunction)

    thisPlayer.find(".total-row .total-not-playing").removeClass("total-playing");
    currentRow.find(".total-not-playing").addClass("total-playing");
}

However, I guess I should use $('body').off("ended") after the triggered function to remove the event listener, as @Fallenreaper has suggested. 但是,我想我应该在触发函数之后使用$('body').off("ended")来删除事件侦听器,如@Fallenreaper建议的那样。

you call songplay inside of a listener, which applies it another time.... and another time and another time. 您在听众内部调用歌曲播放,这将在另一时间....另一时间和另一时间应用它。

recursion. 递归。

>_>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM