Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

カスタムエラーハンドラーをプラグイン化して循環参照を防ぐ #1361

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions samples/web-csr/dressca-frontend/consumer/src/main.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { createApp } from 'vue';
import { createPinia } from 'pinia';
import { authenticationGuard } from '@/shared/authentication/authentication-guard';
import { errorHandlerPlugin } from '@/shared/error-handler/error-handler-plugin';
import { globalErrorHandler } from '@/shared/error-handler/global-error-handler';
import { createCustomErrorHandler } from '@/shared/error-handler/custom-error-handler';
import App from './App.vue';
import { router } from './router';

Expand All @@ -13,7 +14,8 @@ const app = createApp(App);
app.use(createPinia());
app.use(router);

app.use(errorHandlerPlugin);
app.use(globalErrorHandler);
app.use(createCustomErrorHandler());

authenticationGuard(router);

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import type { App } from 'vue';
import { showToast } from '@/services/notification/notificationService';
import { useRoutingStore } from '@/stores/routing/routing';
import { router } from '@/router';
import { customErrorHandlerKey } from '@/shared/injection-symbols';
import {
CustomErrorBase,
UnauthorizedError,
NetworkError,
ServerError,
} from './custom-error';

export interface CustomErrorHandler {
install(app: App): void;
handle(
error: unknown,
callback: () => void,
handlingUnauthorizedError?: (() => void) | null,
handlingNetworkError?: (() => void) | null,
handlingServerError?: (() => void) | null,
): void;
}

export function createCustomErrorHandler(): CustomErrorHandler {
const customErrorHandler: CustomErrorHandler = {
install: (app: App) => {
app.provide(customErrorHandlerKey, customErrorHandler);
},
handle: (
error: unknown,
callback: () => void,
handlingUnauthorizedError: (() => void) | null = null,
handlingNetworkError: (() => void) | null = null,
handlingServerError: (() => void) | null = null,
) => {
// ハンドリングできるエラーの場合はコールバックを実行
if (error instanceof CustomErrorBase) {
callback();

// エラーの種類によって共通処理を行う
// switch だと instanceof での判定ができないため if 文で判定
if (error instanceof UnauthorizedError) {
if (handlingUnauthorizedError) {
handlingUnauthorizedError();
} else {
const routingStore = useRoutingStore();
routingStore.setRedirectFrom(
router.currentRoute.value.path.slice(1),
);
router.push({ name: 'authentication/login' });
showToast('ログインしてください。');
}
} else if (error instanceof NetworkError) {
if (handlingNetworkError) {
handlingNetworkError();
} else {
showToast('ネットワークエラーが発生しました。');
}
} else if (error instanceof ServerError) {
if (handlingServerError) {
handlingServerError();
} else {
showToast('サーバーエラーが発生しました。');
}
}
} else {
// ハンドリングできないエラーの場合は上位にエラーを投げる
throw error;
}
},
};
return customErrorHandler;
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type { App, ComponentPublicInstance } from 'vue';
import { router } from '../../router';

export const errorHandlerPlugin = {
export const globalErrorHandler = {
/* eslint no-param-reassign: 0 */
install(app: App) {
app.config.errorHandler = (
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { inject } from 'vue';
import type { CustomErrorHandler } from './custom-error-handler';
import { customErrorHandlerKey } from '../injection-symbols';

export function useCustomErrorHandler(): CustomErrorHandler {
return inject(customErrorHandlerKey)!;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import type { InjectionKey } from 'vue';
import type { CustomErrorHandler } from './error-handler/custom-error-handler';

export const customErrorHandlerKey = Symbol(
'customErrorHandler',
) as InjectionKey<CustomErrorHandler>;
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import Loading from '@/components/common/LoadingSpinner.vue';
import { currencyHelper } from '@/shared/helpers/currencyHelper';
import { assetHelper } from '@/shared/helpers/assetHelper';
import { storeToRefs } from 'pinia';
import { errorHandler } from '@/shared/error-handler/error-handler';
import { useCustomErrorHandler } from '@/shared/error-handler/use-custom-error-handler';

const state = reactive({
showLoading: true,
Expand All @@ -23,6 +23,7 @@ const basketStore = useBasketStore();
const { getBasket, getAddedItem, getAddedItemId } = storeToRefs(basketStore);

const router = useRouter();
const customErrorHandler = useCustomErrorHandler();
const { toCurrencyJPY } = currencyHelper();
const { getFirstAssetUrl } = assetHelper();

Expand All @@ -38,7 +39,7 @@ const update = async (catalogItemId: number, newQuantity: number) => {
try {
await updateItemInBasket(catalogItemId, newQuantity);
} catch (error) {
errorHandler(error, () => {
customErrorHandler.handle(error, () => {
showToast('数量の変更に失敗しました。');
});
}
Expand All @@ -49,7 +50,7 @@ const remove = async (catalogItemId: number) => {
try {
await removeItemFromBasket(catalogItemId);
} catch (error) {
errorHandler(error, () => {
customErrorHandler.handle(error, () => {
showToast('商品の削除に失敗しました。');
});
}
Expand All @@ -64,7 +65,7 @@ onMounted(async () => {
try {
await fetchBasket();
} catch (error) {
errorHandler(error, () => {
customErrorHandler.handle(error, () => {
showToast('カートの取得に失敗しました。');
});
} finally {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,15 @@ import Loading from '@/components/common/LoadingSpinner.vue';
import { useRouter } from 'vue-router';
import { currencyHelper } from '@/shared/helpers/currencyHelper';
import { assetHelper } from '@/shared/helpers/assetHelper';
import { errorHandler } from '@/shared/error-handler/error-handler';
import { useCustomErrorHandler } from '@/shared/error-handler/use-custom-error-handler';

const specialContentStore = useSpecialContentStore();
const catalogStore = useCatalogStore();

const { getSpecialContents } = storeToRefs(specialContentStore);
const { getCategories, getBrands, getItems } = storeToRefs(catalogStore);
const router = useRouter();
const customErrorHandler = useCustomErrorHandler();

const state = reactive({
selectedCategory: 0,
Expand All @@ -38,7 +39,7 @@ const addBasket = async (catalogItemId: number) => {
await addItemToBasket(catalogItemId);
router.push({ name: 'basket' });
} catch (error) {
errorHandler(error, () => {
customErrorHandler.handle(error, () => {
showToast('カートに追加できませんでした。');
});
}
Expand All @@ -50,7 +51,7 @@ onMounted(async () => {
try {
await fetchItems(selectedCategory.value, selectedBrand.value);
} catch (error) {
errorHandler(error, () => {
customErrorHandler.handle(error, () => {
showToast('商品の取得に失敗しました。');
});
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,15 @@ import { useRouter } from 'vue-router';
import { currencyHelper } from '@/shared/helpers/currencyHelper';
import { assetHelper } from '@/shared/helpers/assetHelper';
import { storeToRefs } from 'pinia';
import { errorHandler } from '@/shared/error-handler/error-handler';
import { useCustomErrorHandler } from '@/shared/error-handler/use-custom-error-handler';

const userStore = useUserStore();
const basketStore = useBasketStore();

const { getBasket } = storeToRefs(basketStore);
const { getAddress } = storeToRefs(userStore);
const router = useRouter();
const customErrorHandler = useCustomErrorHandler();
const { toCurrencyJPY } = currencyHelper();
const { getFirstAssetUrl } = assetHelper();

Expand All @@ -32,7 +33,7 @@ const checkout = async () => {
);
router.push({ name: 'ordering/done', params: { orderId } });
} catch (error) {
errorHandler(error, () => {
customErrorHandler.handle(error, () => {
showToast('注文に失敗しました。');
router.push({ name: 'error' });
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,10 @@ import { showToast } from '@/services/notification/notificationService';
import type { OrderResponse } from '@/generated/api-client/models/order-response';
import { currencyHelper } from '@/shared/helpers/currencyHelper';
import { assetHelper } from '@/shared/helpers/assetHelper';
import { errorHandler } from '@/shared/error-handler/error-handler';
import { useCustomErrorHandler } from '@/shared/error-handler/use-custom-error-handler';

const router = useRouter();
const customErrorHandler = useCustomErrorHandler();
const props = defineProps<{
orderId: number;
}>();
Expand All @@ -28,7 +29,7 @@ onMounted(async () => {
try {
state.lastOrdered = await getOrder(props.orderId);
} catch (error) {
errorHandler(error, () => {
customErrorHandler.handle(error, () => {
showToast('注文情報の取得に失敗しました。');
router.push('/');
});
Expand Down