运行如何在JavaScript中同步运行?

How to Run functions synchronously in JavaScript?

我是 JavaScript 和 React 的新手,我正试图摆脱教程,因此为了我自己的学习利益开始制作一个简单的应用程序,但 运行 遇到了功能 运行宁异步。

onSearchSubmit 中,有一个 setState 在其回调中具有以下内容:

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

如何让上面的这两个函数同步到运行? findSalaryRangeMax 使用 findSalaryRangeMin 中设置的 this.state.salaryLower,但下面的 console.log 显示 findSalaryRangeMaxfindSalaryRangeMin 完成之前触发。

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

我读过一些提到使用 promises 的资源,但我不知道如何应用它...我也想知道是否可以通过 async/await.

完整(大概)代码: (为简单起见,我删除了一些代码)

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 响应不会显示单个工作的薪水范围,但可以通过查询薪水范围相当准确地确定薪水。

setState 是异步的,所以如果你依赖于 运行 下一个函数之前的状态值,你可以这样做:

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

您的理解是正确的,如果您希望函数同步 运行 并且现有代码将 运行 下面的行 findSalaryRangeMax 在返回之前需要异步或承诺所需的数据。

async/await 和 promises 肯定会有帮助,但通常也值得考虑一些代码更改。例如,您可以将这两个函数组合成一个函数,例如

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