Skip to content

Commit c179160

Browse files
committed
✨ feat: 优化歌单竞态条件
1 parent cb3b407 commit c179160

3 files changed

Lines changed: 74 additions & 7 deletions

File tree

src/views/List/liked.vue

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,9 @@ const searchData = ref<SongType[]>([]);
197197
// 歌单 ID
198198
const playlistId = computed<number>(() => dataStore.userLikeData.playlists?.[0]?.id);
199199
200+
// 当前正在请求的歌单 ID,用于防止竞态条件
201+
const currentRequestId = ref<number>(0);
202+
200203
// 加载提示
201204
const loading = ref<boolean>(true);
202205
const loadingMsg = ref<MessageReactive | null>(null);
@@ -276,6 +279,8 @@ const getPlaylistDetail = async (
276279
},
277280
) => {
278281
if (!id) return;
282+
// 设置当前请求的歌单 ID,用于防止竞态条件
283+
currentRequestId.value = id;
279284
// 设置加载状态
280285
loading.value = true;
281286
const { getList, refresh } = options;
@@ -301,6 +306,8 @@ const getPlaylistData = async (id: number, getList: boolean, refresh: boolean) =
301306
loadLikedCache();
302307
// 获取歌单详情
303308
const detail = await playlistDetail(id);
309+
// 检查是否仍然是当前请求的歌单
310+
if (currentRequestId.value !== id) return;
304311
playlistDetailData.value = formatCoverList(detail.playlist)[0];
305312
// 不需要获取列表或无歌曲
306313
if (!getList || playlistDetailData.value.count === 0) {
@@ -311,11 +318,15 @@ const getPlaylistData = async (id: number, getList: boolean, refresh: boolean) =
311318
if (isLogin() === 1 && (playlistDetailData.value?.count as number) < 800) {
312319
const ids: number[] = detail.privileges.map((song: any) => song.id as number);
313320
const result = await songDetail(ids);
321+
// 检查是否仍然是当前请求的歌单
322+
if (currentRequestId.value !== id) return;
314323
// 直接批量详情返回时也进行一次按 id 去重
315324
playlistData.value = uniqBy(formatSongsList(result.songs), "id");
316325
} else {
317326
await getPlaylistAllSongs(id, playlistDetailData.value.count || 0, refresh);
318327
}
328+
// 检查是否仍然是当前请求的歌单
329+
if (currentRequestId.value !== id) return;
319330
// 更新我喜欢
320331
dataStore.setLikeSongsList(playlistDetailData.value, playlistData.value);
321332
loading.value = false;
@@ -347,14 +358,29 @@ const getPlaylistAllSongs = async (
347358
const limit: number = 500;
348359
const listData: SongType[] = [];
349360
do {
361+
// 检查是否仍然是当前请求的歌单
362+
if (currentRequestId.value !== id) {
363+
loadingMsgShow(false);
364+
return;
365+
}
350366
const result = await playlistAllSongs(id, limit, offset);
367+
// 再次检查是否仍然是当前请求的歌单(请求完成后)
368+
if (currentRequestId.value !== id) {
369+
loadingMsgShow(false);
370+
return;
371+
}
351372
const songData = formatSongsList(result.songs);
352373
listData.push(...songData);
353374
// 非刷新模式下,增量拼接时进行去重,避免与缓存或上一页数据重复
354375
if (!refresh) playlistData.value = uniqBy([...playlistData.value, ...songData], "id");
355376
// 更新数据
356377
offset += limit;
357-
} while (offset < count && isLikedPage.value);
378+
} while (offset < count && isLikedPage.value && currentRequestId.value === id);
379+
// 最终检查是否仍然是当前请求的歌单
380+
if (currentRequestId.value !== id) {
381+
loadingMsgShow(false);
382+
return;
383+
}
358384
// 刷新模式下,统一以最终聚合数据为准,并进行去重
359385
if (refresh) playlistData.value = uniqBy(listData, "id");
360386
// 关闭加载

src/views/List/playlist.vue

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,9 @@ const searchData = ref<SongType[]>([]);
245245
const oldPlaylistId = ref<number>(0);
246246
const playlistId = computed<number>(() => Number(router.currentRoute.value.query.id as string));
247247
248+
// 当前正在请求的歌单 ID,用于防止竞态条件
249+
const currentRequestId = ref<number>(0);
250+
248251
// 加载提示
249252
const loading = ref<boolean>(true);
250253
const loadingMsg = ref<MessageReactive | null>(null);
@@ -341,6 +344,8 @@ const getPlaylistDetail = async (
341344
options: { getList: boolean; refresh: boolean } = { getList: true, refresh: false },
342345
) => {
343346
if (!id) return;
347+
// 设置当前请求的歌单 ID,用于防止竞态条件
348+
currentRequestId.value = id;
344349
// 设置加载状态
345350
loading.value = true;
346351
const { getList, refresh } = options;
@@ -375,6 +380,8 @@ const handleOnlinePlaylist = async (id: number, getList: boolean, refresh: boole
375380
376381
// 获取歌单详情
377382
const detail = await playlistDetail(id);
383+
// 检查是否仍然是当前请求的歌单
384+
if (currentRequestId.value !== id) return;
378385
playlistDetailData.value = formatCoverList(detail.playlist)[0];
379386
const count = playlistDetailData.value?.count || 0;
380387
// 不需要获取列表或无歌曲
@@ -386,10 +393,14 @@ const handleOnlinePlaylist = async (id: number, getList: boolean, refresh: boole
386393
if (isLogin() === 1 && count === detail.privileges?.length && count < 800) {
387394
const ids = detail.privileges.map((song: any) => song.id as number);
388395
const result = await songDetail(ids);
396+
// 检查是否仍然是当前请求的歌单
397+
if (currentRequestId.value !== id) return;
389398
playlistData.value = formatSongsList(result.songs);
390399
} else {
391400
await getPlaylistAllSongs(id, count, refresh);
392401
}
402+
// 检查是否仍然是当前请求的歌单
403+
if (currentRequestId.value !== id) return;
393404
loading.value = false;
394405
};
395406
@@ -408,13 +419,28 @@ const getPlaylistAllSongs = async (
408419
const limit: number = 500;
409420
const listData: SongType[] = [];
410421
do {
422+
// 检查是否仍然是当前请求的歌单
423+
if (currentRequestId.value !== id) {
424+
loadingMsgShow(false);
425+
return;
426+
}
411427
const result = await playlistAllSongs(id, limit, offset);
428+
// 再次检查是否仍然是当前请求的歌单(请求完成后)
429+
if (currentRequestId.value !== id) {
430+
loadingMsgShow(false);
431+
return;
432+
}
412433
const songData = formatSongsList(result.songs);
413434
listData.push(...songData);
414435
if (!refresh) playlistData.value = playlistData.value.concat(songData);
415436
// 更新数据
416437
offset += limit;
417-
} while (offset < count && isPlaylistPage.value);
438+
} while (offset < count && isPlaylistPage.value && currentRequestId.value === id);
439+
// 最终检查是否仍然是当前请求的歌单
440+
if (currentRequestId.value !== id) {
441+
loadingMsgShow(false);
442+
return;
443+
}
418444
if (refresh) playlistData.value = listData;
419445
// 关闭加载
420446
loadingMsgShow(false);

src/views/List/radio.vue

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,9 @@ const searchData = ref<SongType[]>([]);
201201
const oldRadioId = ref<number>(0);
202202
const radioId = computed<number>(() => Number(router.currentRoute.value.query.id as string));
203203
204+
// 当前正在请求的播客 ID,用于防止竞态条件
205+
const currentRequestId = ref<number>(0);
206+
204207
// 加载提示
205208
const loading = ref<boolean>(true);
206209
const loadingMsg = ref<MessageReactive | null>(null);
@@ -244,10 +247,7 @@ const moreOptions = computed<DropdownOption[]>(() => [
244247
key: "copy",
245248
props: {
246249
onClick: () =>
247-
copyData(
248-
`https://music.163.com/#/djradio?id=${radioId.value}`,
249-
"已复制分享链接到剪贴板",
250-
),
250+
copyData(`https://music.163.com/#/djradio?id=${radioId.value}`, "已复制分享链接到剪贴板"),
251251
},
252252
icon: renderIcon("Share"),
253253
},
@@ -266,13 +266,16 @@ const moreOptions = computed<DropdownOption[]>(() => [
266266
// 获取播客基础信息
267267
const getRadioDetail = async (id: number) => {
268268
if (!id) return;
269+
// 设置当前请求的播客 ID,用于防止竞态条件
270+
currentRequestId.value = id;
269271
// 设置加载状态
270272
loading.value = true;
271273
// 清空数据
272274
clearInput();
273275
// 获取播客详情
274276
radioDetailData.value = null;
275277
const detail = await radioDetail(id);
278+
if (currentRequestId.value !== id) return;
276279
radioDetailData.value = formatCoverList(detail.data)[0];
277280
// 获取全部节目
278281
await getRadioAllProgram(id, radioDetailData.value?.count as number);
@@ -289,12 +292,24 @@ const getRadioAllProgram = async (id: number, count: number) => {
289292
let offset: number = 0;
290293
const limit: number = 500;
291294
do {
295+
if (currentRequestId.value !== id) {
296+
loadingMsgShow(false);
297+
return;
298+
}
292299
const result = await radioAllProgram(id, limit, offset);
300+
if (currentRequestId.value !== id) {
301+
loadingMsgShow(false);
302+
return;
303+
}
293304
const songData = formatSongsList(result.programs);
294305
radioListData.value = radioListData.value.concat(songData);
295306
// 更新数据
296307
offset += limit;
297-
} while (offset < count && isPlaylistPage.value);
308+
} while (offset < count && isPlaylistPage.value && currentRequestId.value === id);
309+
if (currentRequestId.value !== id) {
310+
loadingMsgShow(false);
311+
return;
312+
}
298313
// 关闭加载
299314
loadingMsgShow(false);
300315
};

0 commit comments

Comments
 (0)