Запуск функции после асинхронной функции в JavaScript - PullRequest
1 голос
/ 11 июня 2019

Я пытаюсь написать код, который запускает асинхронную функцию, и когда это выполнено, он запускает другой кусок кода.

Я попытался поместить асинхронную функцию в обещание (как видно из кода ниже)и использование метода 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 ]

2 голосов
/ 11 июня 2019

Будучи определенным как async, ваш getDataAndUsername уже является Обещанием, нет необходимости заключать его в new Promise(). Вы можете просто сделать:

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

И это должно работать.

Почему ваш код вообще не работал

Вы создавали новое обещание с этим:

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

Там вы звоните this.getDataAndUsername(), но игнорируете, разрешает он или нет. Этот код вызовет res мгновенно, поэтому checkInDatabase вызывался до того, как getDataAndUsername разрешился.

Вам холодно, вместо этого дождитесь разрешения getDataAndUsername:

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

Смысл в том, чтобы дождаться разрешения обещания, используя then, а также добавив return.

Однако, как указано выше, делать это не нужно, поскольку getDataAndUsername уже является Обещанием.

0 голосов
/ 11 июня 2019

Как я уже писал в комментариях, вы слишком часто обновляете состояние. Это асинхронный процесс, поэтому в конечном итоге вы можете проверить или просмотреть старое состояние.

Я предлагаю вам использовать this.setState как можно меньше и возвращать значения в максимально возможном количестве функций. Таким образом, вы разделите функциональность и не будете полагаться на состояние реакции.

Вот мое предложение по вашей проблеме:

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
      })
    }
  }
}
0 голосов
/ 11 июня 2019

Попробуйте:

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
   */
  }
})();
...