90 lines
2.0 KiB
JavaScript
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' })
|
|
}
|