【问题标题】:async await and promise chain is not waiting to resolve异步等待和承诺链不等待解决
【发布时间】:2021-11-09 17:53:54
【问题描述】:

我将我的 API 调用放在一个新函数中,这样我就可以轻松地用几行代码调用它们,而不是在每个页面上都使用大量代码。我遇到的问题是异步和等待在返回数据之前完成。

我首先得到 console.log(sess.getIdToken().getJwtToken()) 控制台,然后是 undefined for console.log(getMessages),然后是来自 console.log(response) 的数据。

所以 await Auth.currentSession().then(...) 运行但不等待它内部的 axios 调用。如何返回数据以便在 useEffect 中访问?

useEffect(() => {
    async function getMessages() {
        const getMessages = await ApiService.getMessages();
        console.log(getMessages)
    }
    getMessages();
}, []);

async getMessages() {
    return await this.__sendRequest("/default/message", "GET");
}

async __sendRequest(url, method) {
    await Auth.currentSession().then(sess => {
        console.log(sess.getIdToken().getJwtToken())
        axios({
            method: method,
            url: process.env.REACT_APP_USER_URL + url,
            headers: {
                "X-TOKEN-ID": sess.getIdToken().getJwtToken(),
                "addresseeType": "P",
                "content-type": "application/json"
            }
        }).then(function (response) {
            console.log(response)
            return response
        }).catch(err => {
            console.error(err);
        })
    })
}

【问题讨论】:

  • __sendRequest 没有返回任何内容。应该是return Auth.currentSession()...,这个函数不需要async/await
  • 删除所有的.then(),直接填满await

标签: javascript reactjs promise axios


【解决方案1】:

async/await 与promise-chaining (.then(...)) 混合使用是一种使代码过于复杂的非常简单的方法。

我可以看到一些导致此问题不起作用的地方。

  • __sendRequest 中,您没有返回任何内容。
  • 在第一个.then 中,您也缺少回报。

这是一个简化且固定的代码

async __sendRequest(url, method) {
    const sess = await Auth.currentSession()

    console.log(sess.getIdToken().getJwtToken())
    
    const response = await axios({
        method: method,
        url: process.env.REACT_APP_USER_URL + url,
        headers: {
            "X-TOKEN-ID": sess.getIdToken().getJwtToken(),
            "addresseeType": "P",
            "content-type": "application/json"
        }
    })

    console.log(response)

    return response
}

查看其他答案的cmets,了解async/await,返回并调用堆栈https://stackoverflow.com/a/69179763/1728166

【讨论】:

    【解决方案2】:

    有几个问题:

    1. __sendRequest 没有 return,所以当它等待完成时,它会用 undefined 履行它的承诺。
    2. Auth.currentSession() 上的链的承诺不会完全等待 axios 调用,因为这两个链没有以任何方式链接。
    3. (不是您看到过早解决的原因,但仍然是一个问题。)不要过早捕获错误,让它们传播,以便调用者知道出了问题。

    另外,一般情况下,不要将.then/.catchasync/await 混合使用,没有必要(通常​​);只需使用await:

    useEffect(() => {
        async function getMessages() {
            try {
                const getMessages = await ApiService.getMessages();
                console.log(getMessages);
            } catch (error) {
                // ...*** handle/report error...
            }
        }
        getMessages();
    }, []);
    
    async getMessages() {
        return await this.__sendRequest("/default/message", "GET");
    }
    
    async __sendRequest(url, method) {
        const sess = await Auth.currentSession();
        console.log(sess.getIdToken().getJwtToken());
        return await axios({
            method: method,
            url: process.env.REACT_APP_USER_URL + url,
            headers: {
                "X-TOKEN-ID": sess.getIdToken().getJwtToken(),
                "addresseeType": "P",
                "content-type": "application/json"
            }
        });
    }
    

    【讨论】:

    【解决方案3】:

    getMessages() 是异步的,因此您需要使用 await 调用 并使第一行的回调函数异步,以便您可以在其中使用等待。

      useEffect(async () => {
        async function getMessages() {
            const getMessages = await ApiService.getMessages();
            console.log(getMessages)
        }
        await getMessages();
     }, []);
    

    您可以通过将所有 then() 回调转换为 await 并将整个链放在 try/catch 块中来简化 __sendRequest。

    【讨论】:

    • 不,如果您不想等待响应(useEffect 回调不需要),则不必使用 await 调用它。此外,将 async 函数作为回调传递给不处理承诺或将其返回给您的事物通常是不好的做法(useEffect 两者都不做)。
    • useEffect() 正在调用 getMessages() ,这是一个异步函数。他在问“我如何返回数据以便我可以在 useEffect 中访问它”。所以他需要等待useEffect里面的getMessages()返回数据
    • 不,他没有,getMessages 进行自己的状态调用。您没有在 useEffect 回调中使用履行值,没有处理拒绝,也没有在承诺解决后做其他事情。 await 在那里是不必要的。这将是无害的,但同样,useEffect 不会处理您返回的承诺。
    猜你喜欢
    • 1970-01-01
    • 2018-04-17
    • 1970-01-01
    • 2018-02-03
    • 2018-03-05
    • 2019-04-29
    • 2021-12-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多