JavaScript中异步功能后的运行功能

时间:2019-06-11 15:00:26

标签: javascript reactjs asynchronous

我正在尝试编写运行异步功能的代码,完成后将运行另一段代码。

我曾尝试将async函数置于一个promise中(如下面的代码所示),并且使用then方法没有成功。

该函数内部发生的情况并不重要,但无论如何我都将其包括在内,以防万一我误会了。

getData = async(file) =>{
        let data = await fetch(file);
        data = await data.text();
        return(data);
    }

    getDataAndUsername = async() => {
        this.setState({data: JSON.parse(await this.getData("/getData"))});
        this.setState({username: await this.getData("/user")});
        console.log('done');
    }

getDataAndUsername是我尝试在其他功能之前运行的异步功能。

CheckInDataBase = (username) => {
        console.log('checking In DataBase');
        this.state.data.forEach((element)=>{
            if(element.username === username){
                    this.setState({exist: true});
                }
            });
            if (!(this.state.exist)){
            axios.post('/createUser', {"username": username, "status": "Working"});
            this.setState({exist: true});
        }
        }

这是我试图在异步运行后运行的常规功能

这是代码:

new Promise((res) => {
            this.getDataAndUsername();
            res();
        }).then(
            this.CheckInDataBase(this.state.username)
        )

现在发生的是,this.CheckInDatabase在getDataAndUsername完成之前运行。

3 个答案:

答案 0 :(得分:2)

您的async被定义为getDataAndUsername,已经是一个Promise,无需将其包装在new Promise()中。您可以这样做:

this.getDataAndUsername().then( _ => {
  this.CheckInDataBase(this.state.username);
})

它应该可以工作。

为什么您的代码最初不起作用

您正在通过以下方式创建新的承诺:

new Promise((res) => {
            this.getDataAndUsername();
            res();
        }) ...

在那里,您正在呼叫this.getDataAndUsername(),但忽略了它能否解析。该代码将立即调用res,因此checkInDatabasegetDataAndUsername解析之前就已被调用。

您不高兴,请等待getDataAndUsername解决:

new Promise((res) => {
            return this.getDataAndUsername().then(_ => {res()})
        }) ...

重点是等待使用then解决承诺,并添加return

但是,如上所述,由于getDataAndUsername已经是一个承诺,所以不需要这样做。

答案 1 :(得分:0)

正如我在评论中所写,您经常更新状态。这是一个异步过程,因此您可能会通过检查或遍历旧状态来结束。

我建议您尽量减少使用this.setState并在尽可能多的函数中返回值。这样,您就可以拆分功能,而不依赖于react的状态。

这是我对您的问题的建议:

class App extends React.PureComponent {
  getData = async (file) =>{
    let data = await fetch(file);
    return await data.text();
  };

  getDataAndUsername = async () => ({
    data: JSON.parse(await this.getData("/getData")),
    username: JSON.parse(await this.getData("/user"))
  });

  checkInDataBase = ({ username, data }) => {
    console.log('checking In DataBase');
    return !!data.find(element => element.username === username);
  };

  addUser = async username => await axios.post('/createUser', {"username": username, "status": "Working"});

  myCheckFunction = async () => {
    const dataAndUsername = await this.getDataAndUsername();
    if (dataAndUsername) {
      if (!this.checkInDataBase(dataAndUsername)) {
        const newUser = await this.addUser(dataAndUsername.username);
        dataAndUsername.data.push(newUser);
      }
      // A single place where you update the state
      this.setState({
        ...dataAndUsername,
        exists: true
      })
    }
  }
}

答案 2 :(得分:-1)

尝试:

this.getDataAndUsername().then((response) => {
  /**
   * Your code that you want to run after getDataAndUsername
   */
}, (error) => {
  /**
   * Handle error here
   */
});

或使用async/await

(async function() {
  try {
    const dataAndUsername = await this.getDataAndUsername();
    /**
     * Your code that you want to run after getDataAndUsername
     */

  } catch(e) {
    /**
   * Handle error here
   */
  }
})();