随着互联网的高速发展,技术不断的更新迭代,web这一领域技术发展更是快的不行,几年前风靡全球的jQuery,现在看来也遇到了瓶颈,现在web更是讲究框架模块化开发,react/vue/angular等框架就是这web发展所需的时代产物,好了,感慨就到这里吧。。。。。。第一次发博,算是学习之路的一个记录
1.这里主要记录一下qq音乐接口变化的问题,之前qq音乐歌曲地址是不需要vkey这样的参数的,视频上讲的只能指引你,真要掌握、吃透还得靠自己去不断查找,不断发现。所以说,朋友们,发现自己不懂的问题,才是最重要的。
这里贴出视频里suggest.vue的代码
searchMore() {
if (!this.hasMore) {
return
}
this.page++
search(this.query, this.page, this.showSinger, perpage).then((res) => {
if (res.code === ERR_OK) {
this.result = this.result.concat(this._genResult(res.data))
this._checkMore(res.data)
}
})
}
_genResult(data) {
let ret = []
if (data.zhida && data.zhida.singerid) {
ret.push({...data.zhida, ...{type: TYPE_SINGER}})
}
if (data.song) {
ret = ret.concat(this._normalizeSongs(data.song.list))
}
return ret
}
_normalizeSongs(list) {
let ret = []
list.forEach((musicData) => {
if (musicData.songid && musicData.albummid) {
ret.push(createSong(musicData))
}
})
return ret
}
然后是qq音乐接口变化后(需要vkey等参数),缺什么,我们就去找什么
1.首先到api/singer.js下加一个获取vkey的方法
export function getSongVkey (songmid) { // 获取歌曲的vkey
const url = '/getVkey'
const data = Object.assign({}, commonParams, {
callback: 'get002341',
jsonpCallback: 'get002341',
loginUin: 0,
hostUin: 0,
format: 'jsonp',
platform: 'yqq',
needNewCode: 0,
data: `{"req":{"module":"CDN.SrfCdnDispatchServer","method":"GetCdnDispatch","param":{"guid":"5416664912","calltype":0,"userip":""}},"req_0":{"module":"vkey.GetVkeyServer","method":"CgiGetVkey","param":{"guid":"5416664912","songmid":["${songmid}"],"songtype":[0],"uin":"0","loginflag":1,"platform":"20"}},"comm":{"uin":0,"format":"json","ct":20,"cv":0}}`
})
return axios.get(url,{
params:data
}).then((res) => {
return Promise.resolve(res.data)
}).catch((e) => {
console.log(e)
})
}
2.然后到webpack.dev.conf.js中去设置代理请求数据
app.get('/getVkey', function (req, res) {//这里的路径是给前端发送请求的url
const url = 'https://u.y.qq.com/cgi-bin/musicu.fcg'
// axios发送get请求,可以自己配置config
axios.get(url, {
headers: {
referer: 'https://y.qq.com/',
host: 'u.y.qq.com'
},
// params是即将与请求一起发送的url参数,无格式对象/URLSearchParams对象
params: req.query
}).then((response) => {
let rest = response.data
if(typeof rest === 'string') {
let reg = /^\w+\(({[^()]+})\)$/
let matches = rest.match(reg)
if(matches) {
rest = JSON.parse(matches[1])
}
}
res.json(rest)
}).catch((e) => {
console.log(e)
})
})
这里是我们需要的url
以及需要的参数字段及内容
重点是域名后面的参数,不要太刻意关注域名,这是音乐文件的真实地址
common/js/song.js createSong方法参数内容变化
export function createSong(musicData, filename, vkey) {
return new Song({
id: musicData.songid,
mid: musicData.songmid,
singer: filterSinger(musicData.singer),
name: musicData.songname,
album: musicData.albumname,
duration: musicData.interval,
image: `https://y.gtimg.cn/music/photo_new/T002R300x300M000${musicData.albummid}.jpg?max_age=2592000`,
url: `http://dl.stream.qqmusic.qq.com/${filename}?guid=5416664912&vkey=${vkey}&uin=0&fromtag=66`
})
}
2.最后是自己不断的摸索,不断的查找,然后到思否上提问,才找到解决问题的关键所在
先贴出自己suggest.vue的三个函数变化
_normalizeSongs(list, callback) {
if(!list) {
return
}
let rest = []
let index = 1
list.forEach((musicData) => {
if(musicData.songid && musicData.albummid) {
let promise = getSongVkey(musicData.songmid) //获取歌曲filename及vkey
promise.then((res) => {
if(res.code === ERR_OK) {
const filename = res.req_0.data.midurlinfo[0].filename
const vkey = res.req_0.data.midurlinfo[0].vkey
const newSong = createSong(musicData, filename, vkey)
// console.log(newSong)
rest.push(newSong) //将获取到的歌曲加入到数组中
if(index === list.length) {
callback && callback(rest)
}
index++
}
})
}
})
}
_genResult(data, callback) {
let rest = []
if(data.zhida && data.zhida.singername) {
rest.push({...data.zhida,...{type: TYPE_SINGER}})
}
if(data.song) {
this._normalizeSongs(data.song.list, (restdata) => {
rest = rest.concat(restdata)
callback && callback(rest)
})
}
}
search() {
this.hasMore = true
this.page = 1 //当query发生改变时,page重置为1
this.$refs.suggest.scrollTo(0, 0)
search(this.query, this.page, this.showSinger, Perpage).then((res) => {
if(res.code === ERR_OK) {
this._genResult(res.data, (rest) => {
// console.log(rest)
this.result = rest
})
this._checkMore(res.data)
}
})
}
其中searchMore方法也有小小变化
searchMore() {
if(!this.hasMore) {
return
}
this.page++
search(this.query, this.page, this.showSinger, Perpage).then((res) => {
if(res.code === ERR_OK) {
this._genResult(res.data, (rest) => {
this.result = this.result.concat(rest) //把新搜索到的数据拼接到之前搜索到的数据中
})
this._checkMore(res.data)
}
})
}
!!!重点来了,要考的
对比之后会发现,视频里的_normalizeSongs方法和_genResult方法会有一个return的值,我的问题就在这里,因为qq音乐接口参数变化后,需要用到getSongVkey这个方法,这个方法返回的是promise对象,然而我要在循环里执行这个异步方法,没办法在循环外return想要的结果,最后在思否上提问,得到道友的解惑,通过callback这个参数得到我想要的return,在promise.then()中call&&callback(rest),自己想要的结果就会被这个rest收留,然后在其他函数里进行下一步操作,总结说来视频里的某个函数return的结果也是被另外的函数当做参数来进行下一步操作,方法不同,思路不同,得到的结果却是相同的,关键是怎么去看待问题,才能采取相应的方法去应对;思否提问地址https://segmentfault.com/q/1010000016912296,感兴趣的可以去看看,漫漫学习路,记一笔。。。