refactor: refactor search logic & remove rxjs

This commit is contained in:
Rewrite0
2024-09-23 16:07:48 +08:00
parent a2eb8d3537
commit ec2856bf5a
5 changed files with 74 additions and 111 deletions

View File

@@ -1,57 +1,60 @@
import { Observable } from 'rxjs';
import type { Ref } from 'vue';
import type { BangumiRule } from '#/bangumi';
import type { BangumiAPI, BangumiRule } from '#/bangumi';
type EventSourceStatus = 'OPEN' | 'CONNECTING' | 'CLOSED';
export const apiSearch = {
/**
* 番剧搜索接口是 Server Send 流式数据,每条是一个 Bangumi JSON 字符串,
* 使用接口方式是监听连接消息后,转为 Observable 配合外层调用时 switchMap 订阅使用
*/
get(keyword: string, site = 'mikan'): Observable<BangumiRule> {
const bangumiInfo$ = new Observable<BangumiRule>((observer) => {
const eventSource = new EventSource(
`api/v1/search/bangumi?site=${site}&keywords=${encodeURIComponent(
keyword
)}`,
{ withCredentials: true }
);
get() {
const eventSource = ref(null) as Ref<EventSource | null>;
const status = ref<EventSourceStatus>('CLOSED');
const data = ref<BangumiRule[]>([]);
eventSource.onmessage = (ev) => {
try {
const apiData: BangumiAPI = JSON.parse(ev.data);
const data: BangumiRule = {
...apiData,
filter: apiData.filter.split(','),
rss_link: apiData.rss_link.split(','),
};
observer.next(data);
} catch (error) {
console.error(
'[/search/bangumi] Parse Error |',
{ keyword },
'response:',
ev.data
);
}
const keyword = ref('');
const provider = ref('');
const close = () => {
if (eventSource.value) {
eventSource.value.close();
eventSource.value = null;
status.value = 'CLOSED';
}
};
const _init = () => {
status.value = 'CONNECTING';
const url = `api/v1/search/bangumi?site=${
provider.value
}&keywords=${encodeURIComponent(keyword.value)}`;
const es = new EventSource(url, { withCredentials: true });
eventSource.value = es;
es.onopen = () => {
status.value = 'OPEN';
};
eventSource.onerror = (ev) => {
console.error(
'[/search/bangumi] Server Error |',
{ keyword },
'error:',
ev
);
// 目前后端搜索完成关闭连接时会触发 error 事件,前端手动调用 close 不再自动重连
eventSource.close();
es.onmessage = (e) => {
const newData = JSON.parse(e.data) as BangumiRule;
data.value = [...data.value, newData];
};
return () => {
eventSource.close();
es.onerror = (err) => {
console.error('EventSource error:', err);
close();
};
});
};
return bangumiInfo$;
const open = () => {
data.value = [];
_init();
};
return {
keyword,
provider,
status,
data,
open,
close,
};
},
async getProvider() {