Skip to content

fix: 修复BGM只能加载8个NCM歌单#455

Closed
scetayh wants to merge 3 commits into
theme-shoka-x:mainfrom
scetayh:main
Closed

fix: 修复BGM只能加载8个NCM歌单#455
scetayh wants to merge 3 commits into
theme-shoka-x:mainfrom
scetayh:main

Conversation

@scetayh

@scetayh scetayh commented Nov 2, 2025

Copy link
Copy Markdown

问题描述

在博客页面,BGM播放器最多只能加载前8个网易云音乐播放列表。

(补充:后来又发现有时播放器甚至不能加载,但似乎是我的问题,我捣鼓了一些臃肿的hexo插件……)

问题复现

假设在_config.shokax.yml中,用户在audio中添加了10个列表:

# bgm
audio:
- title: 列表1
  list:
    - https://music.163.com/#/playlist?id=[id]
- title: 列表2
  list:
    - https://music.163.com/#/playlist?id=[id]
[ ... ]
- title: 列表10
  list:
    - https://music.163.com/#/playlist?id=[id]

那么在博客页面中,虽从“列表1”到“列表10”的标题均能正常显示,但只有前8个歌单中的歌曲会正常列出和播放;而点击列表9和10时,歌曲并不会被列出来,而是一片空白

原因分析

已经注释过了:

nyx-player在初始化时会对每个配置的播放列表调用Ws.fetchPlaylist(),并且用Promise.all并行发起对外部meting API(也就是api.injahow.cn)的请求。

当播放列表很多时(比如大于8),大量并发请求会触发两类问题之一:

  • 浏览器HTTP并发连接数限制(不同浏览器和不同协议,限制也就不同,常见HTTP/1.1每域6至8个并发连接),导致后续请求被排队或失败;
  • 外部 API(api.injahow.cn)对并发或者频率有限制(返回429错误),一旦其中某个请求失败,Promise.all会直接reject,导致初始化流程中断,后面的播放列表就“没加载”了。

总而言之,并发请求导致部分请求失败或被阻塞,从而让整体初始化失败(emmm,看起来是第9个以后的不起作用)。

解决方案

  // Limit concurrent requests to the external meting API to avoid hitting
  // browser / server limits when many playlists are loaded at once.
  // nyx-player uses `fetch()` internally; we patch `window.fetch` for
  // requests to api.injahow.cn so that they are executed with limited
  // concurrency (serialised or small pool) to avoid Promise.all failing.

我们可以在主题的播放器启动脚本里(不会直接改动第三方包的源码,而是对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-limitasync-pool)。这样能在库层面处理错误,还可以做更细致的重试或降级策略。

此外建议在log或者UI上弄点日志排错。

@sonarqubecloud

sonarqubecloud Bot commented Nov 2, 2025

Copy link
Copy Markdown

@zkz098

zkz098 commented Nov 2, 2025

Copy link
Copy Markdown
Member

nyx-player是一方包,直接改源码就行了,主题里面加个 wrapper 后期容易忘。nyx-player仓库链接

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants