#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
Что-то вроде этого:
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, я последовал вашему подходу, и он сработал. Я опубликовал свою обновленную функцию в вопросе в качестве решения