这个函数只有在数组 defaultArrayMelody 是不同的数字时才会有效 - 一个接一个 - 我的意思是:[5,3,4,2] - 它有效, [5,3,3,2] - 它不起作用。
我怀疑'已结束'的侦听器执行了两次,并为该元素添加了两个事件侦听器。然后该函数循环,它不能按我的意愿工作。如何限制听众的追求?
Java脚本:
function playDefault() {
const defaultArrayMelody = [70, 71, 69, 70];
const audio = defaultArrayMelody.map(el => document.querySelector(`audio[data-key="${el}"]`));
for (let i = 0 ; i < defaultArrayMelody.length; ++i) {
audio[i].addEventListener('ended', () => {
const index = i + 1;
if (index > audio.length-1) return false;
audio[index].play();
});
}
audio[0].play();
}
document.querySelector(`#playDefault`).addEventListener('click', playDefault);
HTML:
<button class="button" id="playDefault">Play Default</button>
<audio data-key="67" src="sounds/c1.wav"></audio>...
答案 0 :(得分:0)
一旦结束听众发射,你需要移除它,所以它不会再被解雇
但是,你添加事件监听器的方式(基本上都是一次)意味着你已经多次为多次播放的音频添加了多个监听器,所以如果重复的音频不是。在阵列中的最后一个,毫无疑问,你会得到一些问题
理想的解决方案是仅在音频启动时添加侦听器,并在ended
事件触发后删除侦听器。
这些答案包括评论中的可选&#34;暂停&#34;在音频元素播放之间 - 这由
中的否定数字表示defaultArrayMelody
function playDefault() {
const defaultArrayMelody = [70, 71, -1000, 69, 70];
const audio = defaultArrayMelody.map(el => el < 0 ? -el : document.querySelector(`audio[data-key="${el}"]`));
var playAudio = function(index) {
if (audio[index]) {
var listener = function() {
this.removeEventListener('ended', listener);
playAudio(index + 1);
};
if (typeof audio[index] == 'number') {
setTimeout(() => playAudio(index + 1), audio[index]);
} else {
audio[index].addEventListener('ended', listener);
audio[index].play();
}
}
};
playAudio(0);
}
document.querySelector(`#playDefault`).addEventListener('click', playDefault);
另一种方法是使用Promise
function playDefault() {
const defaultArrayMelody = [70, 71, -1000, 69, 70];
const audio = defaultArrayMelody.map(el => el < 0 ? -el : document.querySelector(`audio[data-key="${el}"]`));
audio.reduce((prev, item) => prev.then(() => new Promise(resolve => {
var listener = function listener() {
this.removeEventListener('ended', listener);
resolve();
};
if (typeof item== 'number') {
setTimeout(resolve, item); // item is millseconds
} else {
item.addEventListener('ended', listener);
item.play();
}
})), Promise.resolve());
}
document.querySelector(`#playDefault`).addEventListener('click', playDefault);
在这里,您可能不会删除事件监听器,因为事件监听器唯一能做的就是解决承诺 - 一旦解决了承诺,就无法再解决(或拒绝) - 从而确保序列只按顺序播放一次。但是,在上面的代码中我包含了removeEventListener ...没有它,代码看起来像
function playDefault() {
const defaultArrayMelody = [70, 71, -1000, 69, 70];
const audio = defaultArrayMelody.map(el => el < 0 ? -el : document.querySelector(`audio[data-key="${el}"]`));
audio.reduce((prev, item) => prev.then(() => new Promise(resolve => {
if (typeof item== 'number') {
setTimeout(resolve, item); // item is millseconds
} else {
item.addEventListener('ended', resolve);
item.play();
}
})), Promise.resolve());
}
document.querySelector(`#playDefault`).addEventListener('click', playDefault);