iptv-app/ui/public/checkWorker.js
2026-02-04 18:02:26 +08:00

90 lines
2.0 KiB
JavaScript

/**
* Web Worker: 后台检测频道可用性
* 使用 Image 加载方式检测(更可靠)
*/
self.onmessage = async function(e) {
const { channels, timeout = 2000, concurrency = 5 } = e.data
// 收集所有源
const allSources = []
for (const ch of channels) {
for (let i = 0; i < ch.sources.length; i++) {
allSources.push({
channelId: ch.id,
channelName: ch.name,
url: ch.sources[i].url,
sourceIndex: i
})
}
}
let completed = 0
const total = allSources.length
// 检测单个源 - 使用 Image 加载检测
function checkSource(source) {
return new Promise((resolve) => {
const startTime = performance.now()
// 对于视频流,尝试用 fetch 快速检测
const controller = new AbortController()
const timer = setTimeout(() => {
controller.abort()
resolve({
...source,
status: 'offline',
delay: 99999
})
}, timeout)
fetch(source.url, {
method: 'HEAD',
signal: controller.signal,
mode: 'no-cors',
cache: 'no-store'
}).then(() => {
clearTimeout(timer)
const delay = Math.round(performance.now() - startTime)
resolve({
...source,
status: 'online',
delay
})
}).catch(() => {
clearTimeout(timer)
resolve({
...source,
status: 'offline',
delay: 99999
})
})
})
}
// 分批并发处理
for (let i = 0; i < allSources.length; i += concurrency) {
const batch = allSources.slice(i, i + concurrency)
const promises = batch.map(source =>
checkSource(source).then(result => {
completed++
self.postMessage({
type: 'progress',
data: {
total,
completed,
current: result.channelName,
result
}
})
})
)
await Promise.all(promises)
}
// 完成
self.postMessage({ type: 'complete' })
}