繁体   English   中英

异步等待未按预期工作:ReactJS

[英]Async Await is not working as expected: ReactJS

我有这个问题,用户必须在成功登录时重定向到相应的仪表板。 假设用户在两个配置文件“p1”和“p2”中有帐户。 登录成功后,我正在获取 API 以查看用户是否有相应配置文件的条目。

1)假设如果用户在 p1 中有条目,我需要将他重定向到“p1”仪表板;

2) 如果在 p2 中有条目,则将他重定向到“p2”仪表板。

3)如果p1或p2中都没有条目,则重定向到配置页面,他可以在其中进行一些条目。

4)如果在这两个配置文件中,那么用户将被要求 select 一个相应的仪表板

现在就我而言,我编写的代码没有按预期工作。 即使我在“p2”中没有帐户,但在“p1”中有帐户,它也会将我带到配置页面。 有人可以帮忙看看这段代码有什么问题吗?

请注意, fetch 调用工作正常。 它给了我一系列的项目。 如果不存在任何项目,则返回一个空数组

// On login 
  handleLogin = async () => {
        // after successful signin
        await Promise.all([
          this.setDashboard("p1"),
          this.setDashboard("p2"),
        ]);
        this.navigateToDashboards();
  };

   setDashboard = async (profile) => {
    let response, value;
    let type = profile;
    if (type === "p1") {
      response = await this.fetchUserAccounts(type);
      value = !!response && response.length ? true : false;
      this.setState({ isP1: value });
    } else {
      response = await this.fetchUserAccounts(type);
      value = !!response && response.length ? true : false;
      this.setState({ isP2: value });
    }
  };

  fetchUserAccounts = async (type) => {
    try {
      let response = await fetch({
        url: "/fetch/entries",
        method: "POST",
        body: {
          profile: type,
        }
      );
      return response.json();
    } catch (error) {
      console.log(error);
    }
  };


    navigateToDashboards = () => {
    let { isP1, isP2 } = this.state;
    if (isP1 && isP2) {
      // CODE FOR PROMPTING WHICH DASHBOARD TO GO
    } else if (!isP1 && !isP2) {
      this.props.history.push("/configpage"); 
    } else if (isP1) {
      this.props.history.push("/p1dashboard");
    } else if (isP2) {
      this.props.history.push("/p2dashboard");
    }
  };

您在上面编写的代码存在一些问题,它们可能比我们在代码段中看到的更深 - 为什么在客户端而不是从服务器发送仪表板类型的逻辑?

还有在cloudType方法中未指定的setDashboard

我不知道您要达到什么目的,所以我猜-您可能应该在componentDidMount中使用fetchUserAccounts并将响应保存在 state 中。

我用一个TODO:在代码中:

class X extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      p1: null,
      p2: null,
    };
  }

  async componentDidMount() {
    const [p1, p2] = await Promise.all([
      this.fetchUserAccounts('p1'),
      this.fetchUserAccounts('p1'),
    ]);
    // NOTE: setState has a second parameter, which is a callback – this way you make sure that the state has been updated – read more here:
    // https://reactjs.org/docs/react-component.html#setstate
    this.setState(s => ({ ...s, p1, p2 }), this.navigateToDashboards);
  }

  fetchUserAccounts = async (type) => {
    try {
      let response = await fetch({
        url: "/fetch/entries",
        method: "POST",
        body: {
          profile: type,
        },
      });
      return response.json();
    } catch (error) {
      console.log(error);
    }
  };

  navigateToDashboards = () => {
    const { history } = this.props;
    const { p1, p2 } = this.state;
    // TODO: Implement your logic how you decide 
    if (isP1 && isP2) {
      // CODE FOR PROMPTING WHICH DASHBOARD TO GO
      return;
    }
    if (isP1) return history.push('/p1dashboard');
    if (isP2) return history.push('/p2dashboard');
    return history.push('/configpage');
  }
}

如果这不起作用,至少看看代码结构。 有些地方不需要else语句。 使用setState的 function 版本。 利用对象/数组解构。 您还应该根据.?response && response:length; true : false;了解 JS 世界中true false .?response && response:length; true : false; 线条——或者我在这里遗漏了一些东西。

问题是您使用async / await错误。

await适用于 promise - 你给它一个 promise,它等待它解决/拒绝。 如果你不给它一个承诺——就像传递一个立即解决的 promise 一样。

您的setDashboard function 没有返回 promise,所以会发生以下代码:

await Promise.all([
          this.setDashboard("p1"),
          this.setDashboard("p2"),
        ]);

实际上会立即解决,但直到this.navigateToDashboards();才执行setDashboard函数; . 为什么? 因为它们被定义为异步,这将它们置于事件循环中。 然后进入await ,但它立即解决,因为里面的函数没有返回 promise (嗯,它确实,因为它是异步的,但它就像写return promise.resolve()作为第一行 - 所以await什么都不做仅将 function 放在事件循环中)- 代码继续以同步方式执行,直到到达 function 的末尾(例如,执行this.navigateToDashboards(); ,然后才进入事件循环并执行setDashboards函数。

在同一主题上, response = await this.fetchUserAccounts(type); 行也有多余的等待,因为fetchUserAccounts()不返回 promise。

要正确使用异步/等待 - 确保您的async function 返回 promise,例如:

setDashboard = async (profile) => {
 return new Promise( resolve, reject => {
    let response, value;
    let type = profile;
    if (type === "p1") {
      response = await this.fetchUserAccounts(type);
      value = !!response && response.length ? true : false;
      this.setState({ isP1: value });
      resolve();
    } else {
      response = await this.fetchUserAccounts(cloudType);
      value = !!response && response.length ? true : false;
      this.setState({ isP2: value });
      resolve();
    }
  })
};

至于 fetchUserAccount:

fetchUserAccounts = async (type) => {
  return new Promise( resolve, reject => {
    try {
      let response = await fetch({
        url: "/fetch/entries",
        method: "POST",
        body: {
          profile: type,
        }
      );
      resolve(response.json());
    } catch (error) {
      console.log(error);
      reject(error);
    }
  }
};

请注意,您现在必须使用.catch处理 promise 拒绝,否则您将收到unhandled promise rejection error

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM