fix: 修复 bangumi search API 中的流式接口,webui 对应接口定义方法改造

- StreamingResponse 换成 EventSourceResponse,即 Server Send Event Source 方式发送数据
- webui 中 search 接口改成 rxjs Observable 方式,
  这次来不及改到 vue 里,但是写了接口 usage example;
- 顺手补了一些 vscode 通用的开发配置,
  补了之前配置文件解析漏了一个可用环境变量的 host 字段
This commit is contained in:
zthxxx
2023-08-31 23:48:07 +08:00
parent 16bbf6f866
commit 7d50e360ed
12 changed files with 177 additions and 23 deletions

View File

@@ -1,11 +1,80 @@
import {
Observable,
} from 'rxjs';
import type { BangumiRule } from '#/bangumi';
export const apiSearch = {
async get(keyword: string, site = 'mikan') {
const { data } = await axios.get('api/v1/search', {
params: {
site,
keyword,
},
/**
* 番剧搜索接口是 Server Send 流式数据,每条是一个 Bangumi JSON 字符串,
* 使用接口方式需要订阅使用
*
* Usage Example:
*
* ```ts
* import {
* Subject,
* tap,
* map,
* switchMap,
* debounceTime,
* } from 'rxjs';
*
*
* const input$ = new Subject<string>();
* const onInput = (e: Event) => input$.next(e.target);
*
* // vue: <input @input="onInput">
*
* const bangumiInfo$ = apiSearch.get('魔女之旅');
*
* // vue: start loading animation
*
* input$.pipe(
* debounceTime(1000),
* tap((input: string) => {
* console.log('input', input)
* // clear Search Result List
* }),
*
* // switchMap 把输入 keyword 查询为 bangumiInfo$ 流,多次输入停用前一次查询
* switchMap((input: string) => apiSearch(input, site)),
*
* tap((bangumi: BangumiRule) => console.log(bangumi)),
* tap((bangumi: BangumiRule) => {
* console.log('bangumi', bangumi)
* // set bangumi info to Search Result List
* }),
* ).subscribe({
* complete() {
* // end of stream, stop loading animation
* },
* })
* ```
*/
get(keyword: string, site = 'mikan'): Observable<BangumiRule> {
const bangumiInfo$ = new Observable<BangumiRule>(observer => {
const eventSource = new EventSource(
`api/v1/search?site=${site}&keyword=${encodeURIComponent(keyword)}`,
{ withCredentials: true },
);
eventSource.onmessage = ev => {
try {
const data: BangumiRule = JSON.parse(ev.data);
observer.next(data);
} catch (error) {
observer.error(error);
}
};
eventSource.onerror = ev => observer.error(ev);
return () => {
eventSource.close();
};
});
return data!;
return bangumiInfo$;
},
};