Как запускать функции синхронно в JavaScript? - PullRequest
0 голосов
/ 11 ноября 2019

Я новичок в JavaScript и React и пытаюсь отойти от учебников, поэтому я начал создавать простое приложение для собственной учебной выгоды, но столкнулся с препятствиями с функциями, выполняемыми асинхронно.

In onSearchSubmit, есть setState, который имеет в своем обратном вызове следующее:

this.findSalaryRangeMin(data.advertiser.id, data.teaser);
this.findSalaryRangeMax(data.advertiser.id, data.teaser);

Как я могу заставить эти две функции выше работать синхронно? findSalaryRangeMax использует this.state.salaryLower, который установлен в findSalaryRangeMin, но console.log ниже показывает, что findSalaryRangeMax срабатывает до завершения findSalaryRangeMin.

  findSalaryRangeMax = (advertiserId, teaser) => {
    console.log(`this.state.salaryLower: `, this.state.salaryLower);
    // ... More code
  };

Я читал некоторые ресурсыв которых упоминается использование обещаний, но я не смог понять, как их применять ... Мне также интересно, можно ли этого достичь с помощью async / await.

Full (ish) Код: (я удалил некоторый код для простоты)

import React from "react";
import JobSearch from "../api/jobSearch"; // axios
import SearchBar from "./SearchBar";

class App extends React.Component {
  state = {
    jobTitle: "",
    advertiser: "",
    salaryLower: "",
    salaryLowerTop: "",
    salaryUpper: "",
    salaryUpperTop: ""
  };

  findSalaryRangeMin = (advertiserId, teaser) => {
    this.setState({ salaryLower: 0, salaryLowerTop: 200000 }, async () => {
      let salaryLowerPrev;
      for (var i = 0; i < 20; i++) {
        const response = await JobSearch.get(
          `http://localhost:3001/salary-range/${advertiserId}/${this.state.salaryLower}/${this.state.salaryLowerTop}/${teaser}`
        );
        console.log(response);
        if (response.data.totalCount === 1) {
          salaryLowerPrev = this.state.salaryLowerTop;
          this.setState({
            salaryLowerTop: Math.round(
              (this.state.salaryLowerTop - this.state.salaryLower) / 2 +
                this.state.salaryLower
            )
          });
        } else {
          this.setState(
            {
              salaryLowerTop: salaryLowerPrev
            },
            () => {
              this.setState({
                salaryLower: Math.round(
                  (this.state.salaryLowerTop - this.state.salaryLower) / 2 +
                    this.state.salaryLower
                )
              });
            }
          );
        }
      }
    });
  };

  findSalaryRangeMax = (advertiserId, teaser) => {
    console.log(`this.state.salaryLower: `, this.state.salaryLower);
    // ... More code
  };

  onSearchSubmit = async term => {
    const response = await JobSearch.get(
      `http://localhost:3001/job-info/${term}`
    );
    if (response.data.totalCount === 1) {
      const data = response.data.data[0];
      this.setState(
        {
          jobTitle: data.title,
          advertiser: data.advertiser.description
        },
        () => {
          this.findSalaryRangeMin(data.advertiser.id, data.teaser);
          this.findSalaryRangeMax(data.advertiser.id, data.teaser);
        }
      );
    } else {
      console.log("totalCount not equal to 1: ", response.data.totalCount);
    }
  };

  render() {
    return (
      <div>
        <SearchBar onSearchSubmit={this.onSearchSubmit} />
        <hr />
        <div>
          Job Title: {this.state.jobTitle}
          Advertiser: {this.state.advertiser}
          Salary Lower Range: {this.state.salaryLower}
          Salary Upper Range: {this.state.salaryUpper}
        </div>
      </div>
    );
  }
}

export default App;

Чтобы дать некоторый контекст, приложение, которое я пытаюсь создать, запрашивает API для сайта списка вакансий. Ответ API не показывает диапазон заработной платы для отдельной работы, но зарплата может быть довольно точно определена путем запроса диапазонов зарплат.

Ответы [ 2 ]

1 голос
/ 11 ноября 2019

Вы правильно понимаете, что асинхронность или обещания необходимы, если вы хотите, чтобы функции выполнялись синхронно и существующий код выполнялся до следующей строки findSalaryRangeMax, прежде чем вернуться с необходимыми данными.

async / await и обещания определенно помогут, но часто стоит подумать и о некоторых изменениях кода. Например, вы можете объединить две функции в одну функцию, такую ​​как

findSalaryRanges(data.advertiser.id, data.teaser)

и получить данные, обработать и установить состояние один раз.

некоторый псевдокод:

findSalaryRanges = async () => {
    // get all the data needed first
    const maxSalaryData = await JobSearch.get(`http://localhost:3001/salary-range/${advertiserId}/${this.state.salaryLower}/${this.state.salaryLowerTop}/${teaser}`);
    const minSalaryData = await JobSearch.get(...);

    // process data as needed
    ...

    // set state once
    this.setState({
        salaryTop: salaryTop,
        salaryLower: salaryLower
    });
};
0 голосов
/ 11 ноября 2019

setState является асинхронным, поэтому, если вы зависите от значения состояния перед запуском следующей функции, вы можете сделать что-то вроде:

this.setState({
  salaryLowerTop: Math.round(
    (this.state.salaryLowerTop - this.state.salaryLower) / 2 +
      this.state.salaryLower
    )
}, () => this.findSalaryRangeMax(data.advertiser.id, data.teaser))

Могу ли я выполнить функцию после завершения setStateобновление

...