Open uier opened 1 year ago
for example
async function submit() {
const [data, error] = await wrapper("my_promise")
}
async function wrapper(myPromise) {
try {
const data = await myPromise()
return [data, null]
} catch (error) {
return [null, error?.response?.data?.message || "Unknown error"]
}
}
Related to #42
我可以試著處理看看這一項
@laporchen 上次看這部分有什麼想法嗎?
我覺得初步可以先從抽出 catch (error) 這一塊開始,例如我想到的是改寫成 .then().catch() 然後 catch() 裡放一個 reuse 的 error handling function
This is what I worked on.
import axios from "axios";
interface RequestHandler<T extends Function> {
callback: T;
parameters: T extends (...args: infer U) => unknown ? U : never;
}
function axiosErrorWrapper(error: unknown): string {
if (axios.isAxiosError(error) && error.response?.data?.message) {
return error.response.data.message;
}
return "Unknown error occurred :(";
}
export async function axiosRequestWrapper<
F extends Function,
R extends F extends (...args: unknown[]) => infer R ? R : never,
>(req: RequestHandler<F>): Promise<[null, string] | [R, null]> {
let res: R;
try {
if (req.parameters) {
res = await req.callback(...req.parameters);
} else {
res = req.callback();
}
} catch (error) {
const errorMsg = axiosErrorWrapper(error);
return [null, errorMsg];
}
return [res, null];
}
/* now we can request like this now
const [res, error] = await axiosRequestWrapper({
callback: () => {
return { data: "hello" };
},
parameters: [],
});
if (error === null) {
console.log("got res", res.data);
} else {
console.log("got error :(", error);
}
*/
這是個蠻好的包裝,我之前想很久要不要這樣寫,直到我後來想到,我們現在在一個元件裡如果有這樣的 API Call 都會有兩個 ref,一個 isLoading 跟一個 errorMsg,搭配著這個 API Call 用
所以如果要這樣整個包起來(callback, parameters...)我會傾向用 composable (useXXX),然後連 isLoading 跟 errorMsg 都由 composable 提供,簡單來說會長得類似 useAxios
const { isLoading, error, execute } = useAsync(callback: Function)
function submit() {
if ( isValidForm() ) execute(params);
}
總結一下,我傾向寫一個 useAsync
或先只改 error handling 的部分
最近在學 Nuxt.js,發現它的 useAsyncData
這設計應該就很符合我們的需求?但多了一個 refresh 用來重新抓資料,還有參數有個 watch 可以讓它 reactive,感覺是可以參考下。
附上官方範例:
const { data, pending, error, refresh } = await useAsyncData(
'mountains',
() => $fetch('https://api.nuxtjs.dev/mountains')
)
每個有做 POST/PUT/DELETE 的元件都會有這段 pattern 出現,可以討論是否適合包成 hook
至少 catch 那邊的邏輯可以抽出來
https://github.com/Normal-OJ/new-front-end/blob/c77be186bb4a98d0028a7e1f213ab490d7a4824b/src/pages/course/%5Bname%5D/announcements/new.vue#L33-L53