前几天写了一个简易的音乐播放器,也收到了大家的一些反馈。最大的问题就是总是资源失效,针对这一点昨天我进行了一次重写,也把重构过程中的一些知识点和心得记录下来与大家一起分享。 没怎么写过文章,语句不通或者错误地方也请大家指出,我多多改正。项目地址
下面开始进入正题
现在已经有很多基于binaryify大佬的网易云API的web音乐播放器。界面都很美观体验也不错,但是在大家在使用时还是官方的。
写这个项目的初衷是因为突然想听周杰伦的歌了,然后去网上一搜,试听都要收费了,然后再油猴的市场里翻到了一个能免费听歌曲的在线工具,这段时间也比较喜欢用node,所以就在摸鱼时,用 puppeteer把周杰伦所有的歌曲地址都整理下来了,然后写成了一个简单的网页播放器。并且发了一个沸点,收到了大家很多的评论和点赞,github上面也出现了我人生中的第一次星星,同时也收到了很多反馈,其中最严重的是歌曲失效问题。
第一次解决失效问题
在查找失效原因时,发现了整理的歌曲地址中存在一个有时效性的key,应该就是为了防止我这种人做的处理。解决办法是,我写了一个定时任务,每隔三个小时重新去拉取一次列表。同时将GitHub的体验地址重定向到了我的博客中,使用的是我自己的服务器资源。我的服务器配置很低,3个小时也是为了节省一些资源。
但是,依然会出现间隔性失效的问题。
第二次解决失效问题
这次换了个思路,既然访问源地址有时效性,那么我就直接了当的把所有的歌曲都下载下来,一劳永逸。怎么下载呢,肯定不是手动,手动是没有灵魂的。然后还是node,使用了node 的 request
模块。于是引出了小知识点,同时下载394个文件?肯定不行啊,于是手动实现了一个下载队列的函数,可以自定义同时下载多少个任务数。函数已经写好了,源码或者文章都有。
...
下载完之后又来了一个问题,我存哪里呢?放自己服务器,不可能的。于是选择了七牛云来做储存。get一个小知识点,文件上传七牛云。
至此,再也不用担心歌曲连接失效的问题了,除非唱片公司告我侵权,我给全部删了。。。
关于UI和功能新增的问题
这个项目非常简单,主要是node的知识运用。前端方面只有一个简单的html页面。UI也很难看。如果大家有兴趣可以自己来修改扩展。
一个小槽点
我的node代码里很多地方没有加 ;
大家不要学我,在写node的时候最好把;
加上哈。尤其在require()
后
第一次写这么多话,我的表达能力很差,如果看不懂我说的,可以移步GitHub直接查看源码。就说这么这么多了,溜了溜了。另外我这里招前端开发,1年经验起步。不要实习,坐标河北廊坊。我的微信在文章最后。
一个下载队列函数
前两天写的那个在线播放周杰伦所有歌曲的小项目,因为总是歌曲地址失效,所以准备把歌曲全部下载下来。放到七牛或者其他的云进行储存。
一共是394条数据,同时下载肯定不行的,所以自己手动写了一个下载的方法,只允许最多同时下载5首歌曲。最后封装成了一个通用的方法并且与大家一起交流分享。
/**
* 下载队列
* @param {Number} max @default 5 -最大并行下载数
* @param {Array} list -下载列表
*
* state not : 未下载; loading : 下载中; done : 下载完成
* */
function downloadQueue(list, max) {
for (let i of list) {
i.state = 'not'
}
// 是否下载完成
let allDone = false
const down = () => {
let noIndex = null
let notDownload = null
for (let i = 0; i < list.length; i++) {
const item = list[i]
if (item.state === 'not') {
notDownload = item
noIndex = i
break
}
}
if (!notDownload) {
console.log('全部下载完毕')
allDone = true
return
}
const downLoadings = list.filter(item => item.state === 'loading')
if (downLoadings.length >= max) {
return
}
notDownload.state = 'loading'
console.log(`下载第 ${noIndex} 个`)
down()
setTimeout(() => {
console.log(`下载第 ${noIndex} 个完成`)
console.log(`剩余 ${list.length} 个`)
list[noIndex].state = 'done'
if (allDone) {
return
}
down()
}, 300)
}
down()
}