Асинхронное программирование [последовательные AJAX запросы в redux]

пишу социальную сеть на react nodejs, когда захожу в аккаунт в sessionStorage формируется токен,при каждой перезагрузке токен изменяется на рандомную строку. По этому токену запрашиваю из базы, скажем, друзей.Столкнулся с такой проблемой, http запрос происходит до изменения или формирования токена по этому из базы не получаю желаемые данные. Как понимаю нужно организовать асинхронность, пробовал при помощи async/await но не получилось, не понимаю как нужно реализовать задачу

         //компонент

function FriendComponent(props) {

         const [load, setLoad] = useState(true)
        useEffect(()=>{
            if(load == true){
                let key = sessionStorage.currentUser
                //обновляю токен во время перезагрузки
                props.dispatch(loadProfile(key,props.history))
                //загружаю полученные данные из базы
                props.dispatch( updateFriends())
                 setLoad(false)
             }
        })

Правильно ли я понял, что проблема в том, что updateFriends() происходит раньше, чем приходит ответ от loadProfile()?
А также, если есть возможность приложить ссылку на репозиторий, сделай, пожалуйста. Больше контекста - всегда хорошо.

Да всё правильно, запрос проходит раньше чем обновление токена,
вот ссылка на репу https://bitbucket.org/overlord9600/social-version2/src/master/
а это диаграмма базы Screenshot_1

Итак, смотри что там происходит:
loadProfile(key,props.history) - это обычный экшен, который ничего не знает об асинхронности, он просто отправляет экшен в редюсер, который потом отправляет запрос через axios.
Простой способ решить проблему: добавить в твой store какой-нибудь флаг, который будет следить за тем, что профиль загрузился, и только после этого запускать updateFriend().

        useEffect(()=>{
            if(load){
                let key = sessionStorage.currentUser
                props.dispatch(loadProfile(key,props.history))
                if (isProfileLoaded) { // вынимаем значение из стора
                   props.dispatch( updateFriends())
                   setLoad(false)
                }
             }
        }, [load, isProfileLoaded])

*обрати внимание на массив зависимостей

Правильный способ - прикрутить какой-нибудь thunk или redux-promise-middleware, который, собственно, для этого и предназначен. Тогда твой экшен будет возвращать Promise и ты сможешь их складывать в цепочку, ну или комбинировать с предыдущим способом:

        useEffect(()=>{
            if(load){
                let key = sessionStorage.currentUser
                props.dispatch(loadProfile(key,props.history))
                .then(() => {
                   props.dispatch( updateFriends())
                   setLoad(false)
                });
             }
        }, [load, isProfileLoaded])

Третий способ - создать отдельный экшен, который будет выстреливать предыдущие два по очереди.

Bonus point:

  1. у тебя все запросы отправляются из редюсера. Я не могу сказать, что это прям антипаттерн, но это точно будет неудобно тестировать.
  2. Должен ли token жить в таблице user? А если пользователь хочет залогиниться одновременно с компьютера и телефона?
2 лайка

спасибо большое за ответ и за советы. мне это очень помогло

1 лайк