|
@@ -0,0 +1,98 @@
|
|
|
+<header>reducers auth</header>
|
|
|
+
|
|
|
+<body>
|
|
|
+ <div id="testDiv">
|
|
|
+ Test
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <script>
|
|
|
+ function jwtDecode(token) { // расщифровки токена авторизации
|
|
|
+ if (!token || typeof token != "string")
|
|
|
+ return undefined;
|
|
|
+ let tokenArr = token.split(".");
|
|
|
+ if (tokenArr.length != 3)
|
|
|
+ return undefined;
|
|
|
+ try {
|
|
|
+ let tokenJsonStr = atob(tokenArr[1]);
|
|
|
+ let tokenJson = JSON.parse(tokenJsonStr);
|
|
|
+ return tokenJson;
|
|
|
+ }
|
|
|
+ catch {
|
|
|
+ return undefined;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ function authReducer(state = {}, action) { // диспетчер обработки login
|
|
|
+ if (action) {
|
|
|
+ if (action.type === 'AUTH_LOGIN') {
|
|
|
+ let newState = { ...state };
|
|
|
+ newState.token = action.token;
|
|
|
+ newState.payload = jwtDecode(action.token);
|
|
|
+ if (!newState.payload) {
|
|
|
+ newState.token = undefined;
|
|
|
+ }
|
|
|
+ return newState;
|
|
|
+ }
|
|
|
+ else if (action.type === 'AUTH_LOGOUT') {
|
|
|
+ let newState = { ...state };
|
|
|
+ newState.token = undefined;
|
|
|
+ newState.payload = undefined;
|
|
|
+ return newState;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return state;
|
|
|
+ }
|
|
|
+
|
|
|
+ function createStore(reducer) {
|
|
|
+ let state = reducer(undefined, {}) //стартовая инициализация состояния, запуск редьюсера со state === undefined
|
|
|
+ let cbs = [] //массив подписчиков
|
|
|
+
|
|
|
+ const getState = () => state //функция, возвращающая переменную из замыкания
|
|
|
+ const subscribe = cb => (cbs.push(cb), //запоминаем подписчиков в массиве
|
|
|
+ () => cbs = cbs.filter(c => c !== cb)) //возвращаем функцию unsubscribe, которая удаляет подписчика из списка
|
|
|
+
|
|
|
+ function dispatch(action) {
|
|
|
+ if (typeof action === 'function') { //если action - не объект, а функция
|
|
|
+ return action(dispatch, getState) //запускаем эту функцию и даем ей dispatch и getState для работы
|
|
|
+ }
|
|
|
+ const newState = reducer(state, action) //пробуем запустить редьюсер
|
|
|
+ if (newState !== state) { //проверяем, смог ли редьюсер обработать action
|
|
|
+ state = newState //если смог, то обновляем state
|
|
|
+ for (let cb of cbs) cb() //и запускаем подписчиков
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return {
|
|
|
+ getState, //добавление функции getState в результирующий объект
|
|
|
+ dispatch,
|
|
|
+ subscribe //добавление subscribe в объект
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ function actionPromise(promise) {
|
|
|
+ return async function Exec(dispatch) {
|
|
|
+ try {
|
|
|
+ const payload = await promise //ожидаем промиса;
|
|
|
+ dispatch(actionAuthLogin(payload)); //сигнализируем redux, что промис успешно выполнен
|
|
|
+ return payload //в месте запуска store.dispatch с этим thunk можно так же получить результат промиса
|
|
|
+ }
|
|
|
+ catch (error) {
|
|
|
+ dispatch(actionLogOut()) //в случае ошибки - сигнализируем redux, что промис несложился
|
|
|
+ }
|
|
|
+ };
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ const actionAuthLogin = token => ({ type: 'AUTH_LOGIN', token });
|
|
|
+ const actionAuthLogout = () => ({ type: 'AUTH_LOGOUT' });
|
|
|
+
|
|
|
+ const store = createStore(authReducer)
|
|
|
+
|
|
|
+ store.subscribe(() => {
|
|
|
+ console.log(store.getState())
|
|
|
+ });
|
|
|
+ const token =
|
|
|
+ "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOnsiaWQiOiI2Mzc3ZTEzM2I3NGUxZjVmMmVjMWMxMjUiLCJsb2dpbiI6InRlc3Q1IiwiYWNsIjpbIjYzNzdlMTMzYjc0ZTFmNWYyZWMxYzEyNSIsInVzZXIiXX0sImlhdCI6MTY2ODgxMjQ1OH0.t1eQlRwkcP7v9JxUPMo3dcGKprH-uy8ujukNI7xE3A0"
|
|
|
+ store.dispatch(actionAuthLogin(token));
|
|
|
+ store.dispatch(actionAuthLogout());
|
|
|
+ </script>
|
|
|
+</body>
|