簡體   English   中英

如何將.then.catch 轉換為 async/await

[英]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。 我發現下面的帖子很好地解釋了它。

如何使用 thunk 和 useDispatch(react-redux 掛鈎)從操作中返回 promise?

考慮任何具有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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM