异步功能循环后如何设置状态

时间:2019-06-19 22:33:06

标签: javascript react-native

我能找到的最接近的答案是这个,因为我需要setState:How do I run a function after using array.map?

,但没有帮助。

我认为答案应该很简单,但是我对Java语言还很陌生。我尝试将isLoading的setState移到拉出所有配置文件之后。

componentDidMount() {
    console.log('MatchesScreen init props: ', Object.keys(this.props))

    Object.keys(this.props.profile.profile.matches).map((username) => {
      console.log('match', username)
      url = 'https://xxxxxxx.execute-api.us-west-2.amazonaws.com/prod/profile?username=' + username
      fetch(url, {
        method: 'GET',
      })
      .then((response) => response.json())
      .then((responseJson) => {
        this.setState({
          isLoading: false,
        })
        this.props.addMatch(responseJson)
      })
      .catch((error) =>{
        console.error(error);
      })
    })
  }

我尝试了各种操作,例如将.then()附加到map函数,但是到目前为止还没有运气。

3 个答案:

答案 0 :(得分:2)

您可以在.map()函数中返回每个诺言,这将给您带来一系列诺言。一旦有了,就可以使用Promise.all()等待数组中的所有promise都解决。

componentDidMount() {
    console.log('MatchesScreen init props: ', Object.keys(this.props))

    // Put all promises into an array
    const promisesArray = Object.keys(this.props.profile.profile.matches).map((username) => {
        console.log('match', username)
        url = 'https://xxxxxxx.execute-api.us-west-2.amazonaws.com/prod/profile?username=' + username;
        // Return each promise
        return fetch(url, {
                method: 'GET',
            })
            .then((response) => response.json())
            .then((responseJson) => {
                this.props.addMatch(responseJson)
            })
            .catch((error) =>{
                console.error(error);
            });
    });

    // Wait for all promises in array to resolve
    Promise.all(promisesArray)
        .then(() => {
            // This will execute once all promises have resolved
            this.setState({
                isLoading: false,
            });
        })
        .catch(e => console.error(e));
}

答案 1 :(得分:0)

尝试使用async / await模式,如下所示:

async componentDidMount() {
...
    Object.keys(this.props.profile.profile.matches).map((username) => {
    ...
      await fetch(url, {
      ...

然后将您的setState方法移到它自己的回调中,您可以在.then()之后的fetch语句中调用它。

我喜欢这个参考文献:https://alligator.io/js/async-functions/

答案 2 :(得分:0)

尝试将Object.keys()包装在while循环中,并在其末尾添加if语句。

var profilesMatched = 0;
while(profilesMatched < Object.keys(this.props.profile.profile.matches).length){
    Object.keys(this.props.profile.profile.matches).map((username) => {
      console.log('match', username)
      url = 'https://xxxxxxx.execute-api.us-west-2.amazonaws.com/prod/profile?username=' + username
      fetch(url, { method: 'GET', })
      .then((response) => {response.json()})
      .then((responseJson) => {
        this.props.addMatch(responseJson);
        profilesMatched++;
      })
      .catch((error) => {
        console.error(error);
      });
    });
    if(profilesMatched == Object.keys(this.props.profile.profile.matches).length){
        this.setState({
          isLoading: false,
        })
    }
}