其他分享
首页 > 其他分享> > 2020.9.9

2020.9.9

作者:互联网

首先简单说一下在项目遇到的问题

问题:自己做的是一个音乐播放器,其中用到vuex这个状态管理工具。出现的一个bug就是每当点击某首歌曲进行播放的时候,我在这时获取这首歌的总时长然后渲染在页面上,这个时间总是上一首歌的总时长。

出问题的地方,播放歌曲方法:
问题代码1
updateSongUrl方法时提交到mutation进行更新歌曲url,这里我await修饰getUrl方法执行完(该方法时一个ajax请求),然后更新url,接着直接修改歌曲播放的状态isPlay,下面我又watch监听了这个状态。(看样子感觉没啥问题.....)

问题代码2
在这一刻我watch到歌曲音频时长是上一首歌的时长。很明显,在songUrl还没更新的时候先拿到了上一首歌的时长,这是异步惹得祸。其实第一张图已经给出了解决方案,设置定时器,等待播放歌曲的方法执行完再通知播放,这时候就能正常拿歌曲时长而不是上一首。
个人认为在歌曲的url还没得到更新之前,watch里面的回调方法就开始执行了。在此我上网查了关于async函数,知道在没有 await 的情况下执行 async 函数,它会立即执行,返回一个 Promise 对象,并且,绝不会阻塞后面的语句。那么我可以这么认为在updateSongUrl()还没完成的时候,就继续执行了下面的状态更新方法,从而导致问题的出现。

完整代码:

methods:

async play (row, column, event) {
      // 更新歌曲的播放状态为关闭
      this.updateIsPlay(false)
      const res = await this.$isPlayed(row.id)
      if (!res.data.success) {
        this.$message({
          type: 'info',
          customClass: 'model-message',
          iconClass: '1',
          message: res.data.message
        })
        return
      }
      // 更新歌曲信息
      this.updateSongInfo(row)
      // 获取歌曲Url
      this.url = await getUrl(row.id)
      this.updateSongUrl(this.url)
      // 通知播放
      setTimeout(() => {
        this.updateIsPlay(true)
      }, 300)
      this.updateIsPlay(true)
      // 判断是否重复点击
      let info
      for (let i = 0; i < this.songList.length; i++) {
        info = this.songList[i]
        this.isRepetSong(info)
      }
      // 更新当前播放歌曲在最近播放中的索引
      for (let i = 0; i < this.renList.length; i++) {
        if (row.id === this.renList[i].id) {
          this.songIndex = i
        }
      }
      this.updateSongIndex(this.songIndex)
      console.log('当前歌曲索引:' + this.songIndex)
    }

watch:

// 监听歌曲播放状态
    isPlay (val) {
      // 获取audio音频对象
      const music = this.$refs.music
      if (val) {
        const judge = () => {
          // 获取歌曲的加载状态
          const state = music.readyState
          if (state >= 3) {
            // 获取歌曲时长
            const long = music.duration
            this.allDuration = Math.floor(long)
            // 获取总时长的分
            const minute = Math.floor(Math.floor(long) / 60)
            // 获取总时长的秒
            const second = Math.floor(long) % 60
            // 将转换之后的时间赋值给歌曲的总时间用于展示
            const time = this.getTime(minute, second)
            this.songTime = time
            console.log('歌曲时长:' + this.songTime)
            // 播放音乐
            music.play()
            this.updateIsPlay(true)
            this.isRepetSong()
            console.log('judge触发了,加载状态' + state)
          } else {
            setTimeout(() => {
              judge()
            }, 200)
          }
        }
        judge()
      } else {
        // 暂停音乐
        music.pause()
      }
    }

标签:const,2020.9,url,歌曲,music,播放,row
来源: https://www.cnblogs.com/ushen/p/16673792.html