小程序[InnerAudioContext]重复播放n次音频

2,355 阅读3分钟

结果

function loopVoice(srcs,maxtimes) {
  let secondIAC = wx.createInnerAudioContext()
  secondIAC.obeyMuteSwitch = false
  secondIAC.onError(() => {
    showToast({
      icon: 'none',
      title: '加载失败',
    })
  })
  let times = 0
  secondIAC.src = src[times]
  secondIAC.onPlay(() => {
    times++
  })
  secondIAC.onEnded(() => {
    if (times === maxtimes) {
      secondIAC.destroy()
    }
    secondIAC.src = src[times]
    secondIAC.play()
  })
  secondIAC.play()
}

起因

今天我在社区发了一个帖子小程序播放同一音频两次要怎么写?想要跟大家探讨一下怎么写好这个功能。

由于我对需求的错误理解,误以为要连续播放两次相同的音频,我踏上了探索之路。

经过与探索

在写网页脚本的过程中,时间监听是我非常喜欢的一系列接口(谁还没个特殊癖好呢),原因当然是因为这些事件一旦触发必有回应,让人觉得非常给力!

有一位前辈曾经指导过我,小程序里的种种功能不过是对网页接口的优化封装与扩充,往往在Web API中都有对应的功能存在,那么我们先来了解一下网页中的监听事件吧!

学习资料:

同一个 EventTarget 注册了多个相同的 EventListener,那么重复的实例会被抛弃。所以这么做不会使得 EventListener 被调用两次,也不需要用 removeEventListener 手动清除多余的EventListener ,因为重复的都被自动抛弃了,前提是options中的capture的参数值一致,如果capture的值不一致,此时就算重复定义,也不会被抛弃掉。

// 改变t2的函数
function modifyTextPlus() {
  console.log("plus")
  var t2 = document.getElementById("t2");
  if (t2.firstChild.nodeValue == "three") {
    console.log('plus +1')
    t2.firstChild.nodeValue = "two";
  } else {
    console.log('plus -1')
    t2.firstChild.nodeValue = "three";
  }
}// 改变t2的函数
function modifyTextMinus() {
  console.log('minus')
  var t2 = document.getElementById("t2");
  if (t2.firstChild.nodeValue == "one") {
    console.log('minus +1')
    t2.firstChild.nodeValue = "two";
  } else {
    console.log('minus -1')
    t2.firstChild.nodeValue = "one";
  }
}

// 为table添加事件监听器
var el = document.getElementById("outside");
el.addEventListener("click", modifyTextPlus, false);
el.addEventListener("click", modifyTextMinus, false);

猜猜这段代码的执行结果是什么样呢?CodePen:点击查看答案

这里多说一句,面试的时候大佬对我使用addEventListener提出了质疑,现在已经不记得具体内容了。大概是说使用on监听的话回调都会被执行,此处还需更进一步探索!

看完了Web API,我们来看一下小程序的API,此处以InnerAudioContext的接口为例。小程序:API文档

可以看到,InnerAudioContext的接口包含了一些基本的控制功能,此外还有一些看着就成双成对的功能函数(这年头代码都要喂狗粮),此处以onEnded和offEnded为例,他们分别代表“监听音频自然播放至结束的事件”和“取消监听音频自然播放至结束的事件”。

一开始呢,我是这样实现目标功能的:

  innerAudioContext.src = "xxxx"
  innerAudioContext.onEnded(() => {
    innerAudioContext.onPlay(() => {
      innerAudioContext.offEnded()
    })
    innerAudioContext.play() 
  })

  innerAudioContext.play()

想要用一个已经定义的全局变量不断得调用play方法来实现多次播放,但是一旦调用了offEnded()之后想重新添加onEnded()就不行了,这样导致了这段代码只能一次使用。

小程序的监听接口与Web API有一点相反,当我添加了多个监听事件后触发时它们都会执行回调。

写到这里我的探索也到了终点,因为终于发现是自己理解错了交互了!