在React组件中使用异步等待(Async await)

14

所以我创建了一个组件,通过我提供的props发送post请求。

虽然我熟悉Async await,但由于某种原因似乎无法返回实际兑现承诺的价值,而只是得到待定状态。

我尝试用更多的函数包装,因为我理解承诺没有被解决。

感觉我漏掉了什么。

以下是我的代码示例

export default class PostController extends React.Component {
constructor(props) {
    super(props)
}
Wrapper = (body) => {
    try{
        let x = this.Send(body);
        return x;
        console.log(x)
    }catch(e){console.log(e)}
}
Send = async (body) => {
        try{
            let data = await this.Post(body);
            return data;
        }catch(e){console.warn(e)}       
}
Post = async (body) => {
    try{
        const options = {
            method: 'POST',
            uri: 'XXXXXXXXXXXXXXXXXXXX',
            body: body
        }
        const data = await rp(options);
        return data; 
    }catch(e){console.warn(e)}
}
render(props) {
    let jsonBody = JSON.stringify(this.props.data)
    const returnData = this.Wrapper(jsonBody)
    console.log(returnData)

        return(
            <div>
                 {(!this.props.data.pw) ? 'Retrieved Password: ' + returnData.message : 'Generated PassWord!:' + returnData.message }
            </div>
        )
    }

你能展示一下 rp(options) 是什么,以及为什么它需要等待某些东西吗?... - Arfeo
请求 Promise 是一个库,它在 Promise 中包装了常规的请求库。 - Scottt
2个回答

11

我认为你需要更多了解JS中的async/await

async函数总是返回一个promise。因此,在Wrapper中,x是一个promise,因为你没有使用await/async

应该像这样:

async Wrapper = (body) => {
    try{
        let x = await this.Send(body); // <-- missing await here
        return x;
    }catch(e){console.log(e)}
}

但是,render 中的代码无法正常工作。因为this.Wrapper()现在返回一个Promise -> returnData 是一个 Promise。而render方法不能是异步函数 :)

render(props) {
    //... 
    const returnData = this.Wrapper(jsonBody) // <-- returnData here is a promise.
    //...

为了让事情正常运转,你需要使用 state。在 componentDidMountcomponentDidUpdate 中调用 this.Wrapper。例如:

constructor() {
    // ...
    this.state = { returnData: null }
}
async componentDidMount() {
   const returnData = await this.Post(...); // Using await to get the result of async func
   this.setState({ returnData });
}

async Post(body) {
  try{
    const options = {
      method: 'POST',
      uri: 'XXXXXXXXXXXXXXXXXXXX',
      body: body
    }
    return rp(options); // define await then return is unnecessary 
  }catch(e){console.warn(e)}
}

render() {
     const { returnData } = this.state;
    // ... Do the rest

}

1
太棒了!没想到可以这样使用componentdidmount!我还有很多要学习的! - Scottt
1
@Scottt:如果这个答案是你需要的,请将其标记为正确答案! - Tan Dat
但是这样不会每次都获取所有帖子吗?这将导致非常低效的代码。 - Sebastian Nielsen
意外的保留字 'await'。我在 async componentDidMount() 中使用它,很奇怪! - Suisse
@Suisse 也许你正在使用不支持异步等待的旧版本? - Tan Dat
@TanDat React的旧版本?O_O 我使用的是npx create-react-app my-app - 不认为那是一个旧版本。很奇怪。 - Suisse

0
我认为你应该尝试将包装函数标记为async,并在控制台记录returnData之前等待它。同时,在Wrapper内部也要等待Send()的执行。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接