最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

reactjs - Running function after async function in javascript - Stack Overflow

programmeradmin2浏览0评论

Im trying to write a code that runs async function and when its done, it runs another piece of code.

I've tried putting the async function in a promise (as seen in the code below) and using the then method without success.

what happens inside the function doesn't really matter but I've included it anyways in case Im mistaking and it does..

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 is the async function Im trying to run before the other functions.

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});
        }
        }

this is the regular function Im trying to run after the async one

and this is the code:

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

whats happenning right now is that, the this.CheckInDatabase runs before the getDataAndUsername is finished.

Im trying to write a code that runs async function and when its done, it runs another piece of code.

I've tried putting the async function in a promise (as seen in the code below) and using the then method without success.

what happens inside the function doesn't really matter but I've included it anyways in case Im mistaking and it does..

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 is the async function Im trying to run before the other functions.

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});
        }
        }

this is the regular function Im trying to run after the async one

and this is the code:

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

whats happenning right now is that, the this.CheckInDatabase runs before the getDataAndUsername is finished.

Share Improve this question asked Jun 11, 2019 at 15:00 eitan reitan r 131 silver badge3 bronze badges 4
  • Why don't you await this.getDataAndUsername();? – sjahan Commented Jun 11, 2019 at 15:08
  • @sjahan becuase theyre not inside a async function, I cant – eitan r Commented Jun 11, 2019 at 15:45
  • You're using this.setState too often in your functions. It's working asynchronously. Try to return the values instead of updating the state. CheckInDataBase might have a problem: the this.setState({exist: true}); inside the loop might not be propagated before the if (!(this.state.exist)) executes – Radu Nemerenco Commented Jun 11, 2019 at 15:50
  • @eitanr if your function is awaiting something, then, it is async, so why not giving it the async keyword? – sjahan Commented Jun 12, 2019 at 8:23
Add a ment  | 

3 Answers 3

Reset to default 4

Being defined as async, your getDataAndUsername is already a Promise, there is no need to wrap it in a new Promise(). You can just do:

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

And it should work.

Why your code didn't work in the first place

You were creating a new promise with this:

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

There, you're calling this.getDataAndUsername(), but are ignoring wether it resolves or not. That code will call res instantly, thus checkInDatabase was being called before getDataAndUsername resolved.

You cold, instead, wait for getDataAndUsername to resolve:

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

The point would be to wait for the promise to resolve using then, and also adding a return.

However, as stated above, there is no need to do this because getDataAndUsername is already a Promise.

As I wrote in the ments, you're updating the state too often. It's an asynchronous process, so you might end up by checking or looping through an old state.

I suggest you to use this.setState as less as possible and return the values instead in as much functions as possible. This way you'll split the functionality and not rely on react's state.

Here is my proposal for your problem:

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
      })
    }
  }
}

Try:

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

Or with async/await:

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

  } catch(e) {
    /**
   * Handle error here
   */
  }
})();
发布评论

评论列表(0)

  1. 暂无评论