Отправка ответа на несколько вызовов api из action для просмотра файла в react js с помощью redux

#reactjs #redux #react-redux #axios

#reactjs #redux #react-redux #axios

Вопрос:

Я новичок в React JS и Redux и застрял в проблеме. Я должен вызвать API входа в систему, и если это вернет успех, мне нужно вызвать другой API, используя axios, чтобы получить данные пользователя. Ниже приведена моя функция в действии, выполняющая это:

  export const login = (username, password) => (dispatch) => {
  return AuthServicee.login(username, password).then(
    (data) => {
      if(data.success) {
        userService.getUserDetails(username).then((data) => {
          localStorage.setItem("user", JSON.stringify(data.data));
          dispatch({
            type: LOGIN_SUCCESS,
            payload: { user: data },
          });
          return Promise.resolve();
        },(error) => {
          const message =
          (error.response amp;amp;
            error.response.data amp;amp;
            error.response.data.message) ||
          error.message ||
          error.toString();
  
          dispatch({
            type: LOGIN_FAIL,
          });
  
          dispatch({
            type: SET_MESSAGE,
            payload: message,
          });
  
          return Promise.reject();
        }).catch(err => {
          dispatch({
            type: LOGIN_FAIL,
          });
        });;   
      } else {
        dispatch({
          type: LOGIN_FAIL,
        });
        dispatch({
          type: SET_MESSAGE,
          payload: data.error,
        });
      }
    },
    (error) => {
      const message =
        (error.response amp;amp;
          error.response.data amp;amp;
          error.response.data.message) ||
        error.message ||
        error.toString();

      dispatch({
        type: LOGIN_FAIL,
      });

      dispatch({
        type: SET_MESSAGE,
        payload: message,
      });

      return Promise.reject();
    }
  );
};
  

Я вызываю указанную выше функцию со своей страницы входа в систему следующим образом:

 const handleLogin = (e) => {
e.preventDefault();
setLoading(true);
form.current.validateAll();
if (checkBtn.current.context._errors.length === 0) {
  dispatch(login(username, password))
    .then(() => {
      setLoading(false);
      if (props !=null amp;amp; props.isAuthenticated) {
        props.history.push("/home");
      }
    })
    .catch(() => {
      setLoading(false);
    });
} else {
  setLoading(false);
}
  

};

Теперь, поскольку я возвращаюсь с первым вызовом API, он возвращает данные, как только первый API предоставляет ответ, и не ждет завершения второго вызова. Он должен дождаться завершения обоих вызовов API, а затем вернуть результат в Login.js . Может кто-нибудь, пожалуйста, помочь мне здесь?
Рабочее решение в соответствии с ответом cb dev

     const login = async (username, password) => {
      try {
        const loginRes = await loginUser(username, password);
        if (loginRes.data != null amp;amp; loginRes.data.success) {
          localStorage.setItem("access_token", loginRes.data.data);
          const getUserRes = await getUserDetail(loginRes.data.data, username);
          localStorage.setItem("user", JSON.stringify(getUserRes.data));
          return getUserRes.data;
        } else {
          return loginRes.data;
        }
      }catch (err) {
          console.log("Something went wrong with the login process...");
          console.log(`I can log the error here: ${err}`);
        }
    }
function loginUser(username, password) {
  return new Promise((resolve, reject) => {
    const response = axios
    .post(API_URL   "users/authenticate", {
      username,
      password,
    });
    resolve(response);
  });
}

function getUserDetail(access_token, username) {
  return new Promise((resolve, reject) => {
    console.log(`Login_step2: I've got ${access_token}...`);
    var url = apiConfig.API_BASE_URL   "users?username=" username;
    resolve (axios.get(url, { headers: authHeader() }));
  });
}
  

Комментарии:

1. Зависит ли второй вызов API от первого?

2. да, я получаю токен из первого вызова api, а затем использую его во втором api для получения подробной информации

Ответ №1:

Вы должны использовать async-await синтаксис. Это сделает ваш код намного приятнее для чтения и будет намного проще контролировать поведение, которое вы намереваетесь.

https://javascript.info/async-await

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/await

Что-то вроде этого:

Ссылка на CodeSandbox

 import React from "react";
import "./styles.css";

function mockLogin_step1() {
  return new Promise((resolve, reject) => {
    setTimeout(() => resolve("Login_step1 success"), 1000);
  });
}

function mockLogin_step2(something) {
  return new Promise((resolve, reject) => {
    console.log(`Login_step2: I've got ${something}...`);
    setTimeout(() => resolve("Login_step2 success"), 1000);
  });
}

function App() {
  async function doLogin() {
    try {
      console.log("Calling async API login STEP 1");
      const step1Result = await mockLogin_step1();
      console.log(step1Result);
      console.log("Calling async API login STEP 2");
      const step2Result = await mockLogin_step2("something from step1");
      console.log(step2Result);
      console.log("I can dispatch something here...");
    } catch (err) {
      console.log("Something went wrong with the login process...");
      console.log("An error probably happened on step1 or step2...");
      console.log(`I can log the error here: ${err}`);
      console.log("I can dispatch something here...");
    }
  }

  return <button onClick={doLogin}>Login</button>;
}

export default App;
  

Результирующий журнал:

введите описание изображения здесь

Комментарии:

1. Спасибо, cddeveloper, я последовал вашему подходу, и он сработал. Я опубликовал свою обновленную функцию в вопросе в качестве решения