hw_19_02_auth.html 4.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. <header>reducers auth</header>
  2. <body>
  3. <div id="testDiv">
  4. Test
  5. </div>
  6. <script>
  7. function jwtDecode(token) { // расщифровки токена авторизации
  8. if (!token || typeof token != "string")
  9. return undefined;
  10. let tokenArr = token.split(".");
  11. if (tokenArr.length != 3)
  12. return undefined;
  13. try {
  14. let tokenJsonStr = atob(tokenArr[1]);
  15. let tokenJson = JSON.parse(tokenJsonStr);
  16. return tokenJson;
  17. }
  18. catch {
  19. return undefined;
  20. }
  21. }
  22. function authReducer(state = {}, action) { // диспетчер обработки login
  23. if (action) {
  24. if (action.type === 'AUTH_LOGIN') {
  25. let newState = { ...state };
  26. newState.token = action.token;
  27. newState.payload = jwtDecode(action.token);
  28. if (!newState.payload) {
  29. newState.token = undefined;
  30. }
  31. return newState;
  32. }
  33. else if (action.type === 'AUTH_LOGOUT') {
  34. let newState = { ...state };
  35. newState.token = undefined;
  36. newState.payload = undefined;
  37. return newState;
  38. }
  39. }
  40. return state;
  41. }
  42. function createStore(reducer) {
  43. let state = reducer(undefined, {}) //стартовая инициализация состояния, запуск редьюсера со state === undefined
  44. let cbs = [] //массив подписчиков
  45. const getState = () => state //функция, возвращающая переменную из замыкания
  46. const subscribe = cb => (cbs.push(cb), //запоминаем подписчиков в массиве
  47. () => cbs = cbs.filter(c => c !== cb)) //возвращаем функцию unsubscribe, которая удаляет подписчика из списка
  48. function dispatch(action) {
  49. if (typeof action === 'function') { //если action - не объект, а функция
  50. return action(dispatch, getState) //запускаем эту функцию и даем ей dispatch и getState для работы
  51. }
  52. const newState = reducer(state, action) //пробуем запустить редьюсер
  53. if (newState !== state) { //проверяем, смог ли редьюсер обработать action
  54. state = newState //если смог, то обновляем state
  55. for (let cb of cbs) cb() //и запускаем подписчиков
  56. }
  57. }
  58. return {
  59. getState, //добавление функции getState в результирующий объект
  60. dispatch,
  61. subscribe //добавление subscribe в объект
  62. }
  63. }
  64. function actionPromise(promise) {
  65. return async function Exec(dispatch) {
  66. try {
  67. const payload = await promise //ожидаем промиса;
  68. dispatch(actionAuthLogin(payload)); //сигнализируем redux, что промис успешно выполнен
  69. return payload //в месте запуска store.dispatch с этим thunk можно так же получить результат промиса
  70. }
  71. catch (error) {
  72. dispatch(actionLogOut()) //в случае ошибки - сигнализируем redux, что промис несложился
  73. }
  74. };
  75. }
  76. const actionAuthLogin = token => ({ type: 'AUTH_LOGIN', token });
  77. const actionAuthLogout = () => ({ type: 'AUTH_LOGOUT' });
  78. const store = createStore(authReducer)
  79. store.subscribe(() => {
  80. console.log(store.getState())
  81. });
  82. const token =
  83. "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOnsiaWQiOiI2Mzc3ZTEzM2I3NGUxZjVmMmVjMWMxMjUiLCJsb2dpbiI6InRlc3Q1IiwiYWNsIjpbIjYzNzdlMTMzYjc0ZTFmNWYyZWMxYzEyNSIsInVzZXIiXX0sImlhdCI6MTY2ODgxMjQ1OH0.t1eQlRwkcP7v9JxUPMo3dcGKprH-uy8ujukNI7xE3A0"
  84. store.dispatch(actionAuthLogin(token));
  85. store.dispatch(actionAuthLogout());
  86. </script>
  87. </body>