fix: cancel parse requests when modal is closed

点击取消解析时,清空 PQueue 队列并中断正在进行的请求。

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-04-10 09:11:10 +08:00
parent ad31301e10
commit 63a7cb347b
2 changed files with 28 additions and 3 deletions
+16 -2
View File
@@ -4,6 +4,7 @@ import (
"encoding/json" "encoding/json"
"errors" "errors"
"fmt" "fmt"
"io"
"math/rand" "math/rand"
"strconv" "strconv"
"strings" "strings"
@@ -80,11 +81,24 @@ func (client *BiliClient) GetPlayInfo(bvid string, cid int) (*PlayInfo, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
body := BaseResV2{} defer response.Body.Close()
err = json.NewDecoder(response.Body).Decode(&body)
// 读取响应体用于调试
bodyBytes, err := io.ReadAll(response.Body)
if err != nil { if err != nil {
return nil, err return nil, err
} }
body := BaseResV2{}
err = json.Unmarshal(bodyBytes, &body)
if err != nil {
// 返回更详细的错误信息
preview := string(bodyBytes)
if len(preview) > 200 {
preview = preview[:200] + "..."
}
return nil, fmt.Errorf("JSON解析失败,响应内容: %s", preview)
}
if body.Code != 0 { if body.Code != 0 {
return nil, errors.New(body.Message) return nil, errors.New(body.Message)
} }
+12 -1
View File
@@ -42,6 +42,8 @@ export class ParseModalComp implements VanComponent {
currentController?: AbortController currentController?: AbortController
parseQueue?: PQueue
allPlayInfo: State<{ allPlayInfo: State<{
page: PageInParseResult page: PageInParseResult
info: PlayInfo | null info: PlayInfo | null
@@ -105,6 +107,8 @@ export class ParseModalComp implements VanComponent {
controller.abort() controller.abort()
} }
this.abortControllers = [] this.abortControllers = []
// 清空解析队列
this.parseQueue?.clear()
}) })
this.element.addEventListener('show.bs.modal', () => { this.element.addEventListener('show.bs.modal', () => {
@@ -116,13 +120,19 @@ export class ParseModalComp implements VanComponent {
async start() { async start() {
this.finishCount.val = 0 this.finishCount.val = 0
this.errorList.val = [] this.errorList.val = []
const queue = new PQueue({ concurrency: 10 }) this.parseQueue = new PQueue({ concurrency: 10 })
const queue = this.parseQueue
for (const page of this.option.workRoute.selectedPages.val) { for (const page of this.option.workRoute.selectedPages.val) {
queue.add(async () => { queue.add(async () => {
// 检查队列是否已被清空(取消解析)
if (queue !== this.parseQueue) return
if (this.totalCount.val == this.finishCount.val) return if (this.totalCount.val == this.finishCount.val) return
const controller = new AbortController() const controller = new AbortController()
this.abortControllers.push(controller) this.abortControllers.push(controller)
const playInfo = await getPlayInfo(page.bvid, page.cid, controller) const playInfo = await getPlayInfo(page.bvid, page.cid, controller)
// 再次检查是否已取消
if (queue !== this.parseQueue) return
playInfo.accept_quality = [...new Set(playInfo.dash.video.map(video => video.id))].sort((a, b) => b - a) playInfo.accept_quality = [...new Set(playInfo.dash.video.map(video => video.id))].sort((a, b) => b - a)
this.allPlayInfo.val = this.allPlayInfo.val.concat({ this.allPlayInfo.val = this.allPlayInfo.val.concat({
page, page,
@@ -132,6 +142,7 @@ export class ParseModalComp implements VanComponent {
}) })
this.finishCount.val++ this.finishCount.val++
}).catch(() => { }).catch(() => {
if (queue !== this.parseQueue) return
this.finishCount.val++ this.finishCount.val++
const badgeNotNum = !page.badge.match(/^\d+$/) const badgeNotNum = !page.badge.match(/^\d+$/)
this.errorList.val = this.errorList.val.concat(`${page.part}${badgeNotNum ? ` - ${page.badge}` : ''}`) this.errorList.val = this.errorList.val.concat(`${page.part}${badgeNotNum ? ` - ${page.badge}` : ''}`)