[英]How to convert .then .catch to async/await
使用 React/Redux 前端和我自己的 nodejs/express api 處理登錄表單/注銷按鈕。 登錄表單有問題。 大多數時候它工作得很好,但我經常犯錯誤。 第一個錯誤是forbidden
的,它告訴我在發送userDetails
請求之前用戶沒有完全通過身份驗證。
然后還有另一個錯誤 Redux 不會改變用戶的角色,我需要動態渲染導航。 我認為將 handleLogin 轉換為 async/await 將是解決方案,但我相信我做得不對。
import React from 'react';
import { login, userDetails } from '../axios/homeApi';
import { useForm } from 'react-hook-form';
import { useDispatch } from 'react-redux';
import { setLogin, setRole } from '../redux/actions';
const LoginForm = () => {
const { handleSubmit, register, errors } = useForm();
const dispatch = useDispatch();
const handleLogin = values => {
login(values.email, values.password)
.then(res => {
const token = res.data.token;
window.localStorage.setItem('auth', token);
dispatch(setLogin({ loggedIn: true }));
userDetails()
.then(res => {
const role = res.data.data.role;
dispatch (setRole({ role }));
})
})
}
return (
<div>
<form action="" onSubmit={handleSubmit(handleLogin)} className="footer-form">
<input
type="email"
placeholder="Enter Email Here"
name="email"
ref={register({ required: "Required Field" })}
/>
<input
type="password"
placeholder="Enter Password Here"
name="password"
ref={register({
required: "Required Field",
minLength: { value: 6, message: "Minimum Length: 6 Characters" }
})}
/>
{errors.password && errors.password.message}
{errors.email && errors.email.message}
<input type="submit" value="Login" />
</form>
</div>
)
}
export default LoginForm;
這是我將 handleLogin 轉換為 async/await 的最佳嘗試。 我試圖了解我應該如何從這些調用中提取數據。
const handleLogin = async values => {
try {
const {data: {token}} = await login(values.email, values.password)
window.localStorage.setItem('auth', token);
console.log(token);
const user = await userDetails();
await dispatch(setLogin({ loggedIn: true}))
await dispatch(setRole(user.data.data.role))
} catch(err) {
console.log(err)
}
}
對此的任何幫助/指導將不勝感激。
當你使用await
時,你必須考慮,變量值與沒有await
返回到res
中的變量值相同。
因此,如果您有:
login(values.email, values.password)
.then(res => {
})
這就像:
var login = await login(values.email, values.password);
所以使用這個邏輯,這個:
login(values.email, values.password)
.then(res => {
const token = res.data.token;
// whatever
userDetails()
.then(res => {
const role = res.data.data.role;
// whatever
})
})
變成:
var login = await login(values.email, values.password)
const token = login.data.token;
// do whatever
var userDetails = await userDetails()
const role = userDetails.data.data.role;
// whatever
檢查此示例的工作原理。 代碼是“相同的”。 一個使用.then
,另一個使用await
。
runThenFunction(); runAwaitFunction(); function runThenFunction(){ console.log("Enter then function") this.returnPromise(2000).then(res => { console.log(res); this.returnPromise(1000).then(res => { console.log(res); }); }); //You can log here and it will be displayed before the promise has been resolved console.log("Exit then function") } async function runAwaitFunction(){ console.log("Enter await function") var firstStop = await returnPromise(1000); console.log(firstStop) var secondStop = await returnPromise(4000); console.log(secondStop) // Using await the code "stops" until promise is resolved console.log("Exit await function") } function returnPromise(time){ return new Promise(resolve => setTimeout(() => resolve("hello: "+time+"ms later."), time)); }
看起來您可能已經有了答案,但在我看來可能是因為您沒有等待 setLogin 的調度完成。 我不知道您的 setLogin 方法是如何設置的,但它必須是一個 thunk。 我發現下面的帖子很好地解釋了它。
考慮任何具有then
屬性的 object,這是一個接受回調作為其第一個參數的 function,例如:
let obj = {
then: callback => callback('hello')
};
await
將任何此類 object 轉換為值then
提供給回調。 所以:
(await obj) === 'hello'
在您的示例中,有兩個實例需要將值返回給then
回調:
login(...).then(res => { /* got res */ });
和
userDetails().then(res => { /* got res */ });
將await
簡單地視為將值返回給對象的then
回調的一種方式! 在這種情況下,對象是login(...)
和userDetails()
的結果,您可以轉換為:
let res = await login(...);
和
let res = await userDetails();
你可以看到這也節省了很多縮進,這是人們喜歡使用async
/ await
的眾多原因之一!
這些從then
-callback-value 到await
的轉換,當插入到您的代碼中時,如下所示:
const handleLogin = async values => {
let loginRes = await login(values.email, values.password);
let token = loginRes.data.token;
window.localStorage.setItem('auth', token);
dispatch(setLogin({ loggedIn: true }));
let userDetailsRes = await userDetails();
let role = userDetailsRes.data.data.role;
dispatch(setRole({ role }));
};
請注意,必須將 function 標記為async
,並且我已將res
重命名為更具體的名稱,因為這兩個響應現在都存在於完全相同的 scope 中,並且需要相互區分。
總的來說,每當您使用then
來獲取回調中的某些值時,您都可以轉換為更優雅的await
等效項。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.