当前位置: 首页 > 知识库问答 >
问题:

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

颛孙航
2023-03-14

我是JavaScript和React的新手,我正试图远离教程,所以为了自己的学习利益,我开始制作一个简单的应用程序,但遇到了功能异步运行的障碍。

onSearchSubmit中,有一个setState,其回调中包含以下内容:

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

如何使上述两个函数同步运行findSalaryRangeMax使用在findSalaryRangeMin中设置的此.state.salaryLower,但下面的控制台.log显示findSalaryRangeMaxfindSalaryRangeMin完成之前启动。

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

我已经阅读了一些参考资料,其中提到使用promise,但我不知道如何应用它。。。我还想知道是否可以通过async/wait实现。

完整(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个答案

夏英发
2023-03-14

setState是异步的,因此如果在运行下一个函数之前依赖于状态值,则可以执行以下操作:

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

是否可以在setState完成更新后执行函数?

施茂
2023-03-14

您的理解是正确的,如果您希望函数同步运行,并且现有代码将运行到以下行findSalaryRangeMax,然后返回所需的数据,则需要异步或promise。

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

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
    });
};
 类似资料:
  • 如何在将GUI保持为活动状态而不是Hibernate/等待状态的同时延迟进程或创建队列?

  • 假设有多个线程由运行相同函数实例的循环组成,但是每个迭代的开始都需要同步(所以首先完成的线程必须等待最后一个线程开始新的迭代)。在C++11中如何做到这一点? ... 这在大多数情况下都起作用,但有时会有一两个线程无法唤醒。 这些是全局变量: 这是在线程中循环运行的函数的末尾:

  • 问题内容: 假设您维护一个公开一个函数的库。您的用户调用它来获取实际数据: 数据被保存在文件中,因此您可以使用内置的Node.js来实现。很明显这两个和是同步的功能。有一天,您被告知将基础数据源切换到只能异步访问的仓库(例如MongoDB)。还被告知要避免惹恼您的用户,API不能更改为仅返回promise或要求回调参数。您如何满足这两个要求? 使用回调/承诺的异步功能是JavasSript和Nod

  • 问题内容: 查看此代码: 正如您在控制台中看到的那样,“动画”功能是异步的,它“分叉”了事件处理程序块代码的流程。事实上 : 遵循块代码的流程! 如果我希望以此行为创建自己的代码,该如何使用javascript/jquery进行创建?我认为这是不使用的策略 问题答案: 您不能创建真正的自定义异步函数。您最终将不得不利用本机提供的技术,例如: 一些HTML5 API,例如文件API,Web数据库AP

  • 问题内容: 首先,这是一个非常特殊的情况,它以错误的方式故意将异步调用改型为一个非常同步的代码库,该代码库长成千上万行,并且当前时间不具备进行更改的能力。对的。” 它伤害了我的每一个生命,但是现实和理想往往并没有相互融合。我知道这很糟糕。 好的,顺便说一句,我该如何做,这样我可以: 示例(或缺少示例)全部使用库和/或编译器,这两种库均不适用于此解决方案。我需要一个如何使其冻结的具体示例(例如,在调

  • 我是新手,所以如果我错过了一些明显的东西,请事先道歉,但是我不知道如何在WebStrem中运行JavaScript。网络Storm留档说只需在浏览器中打开超文本标记语言文件,但这似乎不起作用。不管怎样,一切都在codepen.io. 以下是超文本标记语言(用于简单的天气应用程序): 这是脚本(仍在草稿中,因为它需要扩展以链接到涵盖“天气”所有值的图像): 非常感谢任何帮助!