fix: 修复BGM只能加载8个NCM歌单#455
Closed
scetayh wants to merge 3 commits into
Closed
Conversation
|
Member
|
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.



问题描述
在博客页面,BGM播放器最多只能加载前8个网易云音乐播放列表。
(补充:后来又发现有时播放器甚至不能加载,但似乎是我的问题,我捣鼓了一些臃肿的hexo插件……)
问题复现
假设在
_config.shokax.yml中,用户在audio中添加了10个列表:那么在博客页面中,虽从“列表1”到“列表10”的标题均能正常显示,但只有前8个歌单中的歌曲会正常列出和播放;而点击列表9和10时,歌曲并不会被列出来,而是一片空白。
原因分析
已经注释过了:
nyx-player在初始化时会对每个配置的播放列表调用Ws.fetchPlaylist(),并且用Promise.all并行发起对外部meting API(也就是api.injahow.cn)的请求。当播放列表很多时(比如大于8),大量并发请求会触发两类问题之一:
Promise.all会直接reject,导致初始化流程中断,后面的播放列表就“没加载”了。总而言之,并发请求导致部分请求失败或被阻塞,从而让整体初始化失败(emmm,看起来是第9个以后的不起作用)。
解决方案
我们可以在主题的播放器启动脚本里(不会直接改动第三方包的源码,而是对fetch做“限流”)加入对
api.injahow.cn请求的并发限制。在
import('nyx-player')之前,注入了一个简单的fetch wrapper:当请求包含host = api.injahow.cn时,使用一个小队列把这些请求限制为并发CONCURRENCY(默认设置为了3)个同时进行,其他请求排队执行。这样
nyx-player内部仍然以并行方式调用fetch,但实际并发数被限制,避免触发浏览器或服务器限制或429错误,从而防止Promise.all因单个请求失败而整体失败。我没有直接修改打包后的
nyx-player逻辑,避免直接改第三方包的源代码和后续维护问题,而是用一个本地的低侵入的补丁来解决运行时并发问题。后续展望
诸位可以试试在
nyx-player的源码里把并行请求改为“受限并发”或使用Promise.allSettled加重试逻辑,或者干脆把Promise.all换成并发池(p-limit、async-pool)。这样能在库层面处理错误,还可以做更细致的重试或降级策略。此外建议在log或者UI上弄点日志排错。