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

时间:2019-11-07 15:26:35

标签: javascript reactjs ecmascript-6 async-await react-router

我有一个问题,在其中,必须在成功登录后将用户重定向到相应的仪表板。说用户在两个配置文件“ p1”和“ p2”中拥有帐户。登录成功后,我将获取API,以查看用户是否具有与相应配置文件相对应的条目。

1)说,如果用户在p1中有条目,我需要将他重定向到“ p1”信息中心;

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

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

4)如果在两个配置文件中,都将要求用户选择相应的仪表板

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

请注意,提取调用效果很好!它给了我很多物品。如果没有项目,则返回一个空数组

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

2 个答案:

答案 0 :(得分:1)

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

还有cloudType方法中未指定的setDashboard

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

我想出了类似这样的代码,其中有一个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的功能版本。利用对象/数组的解散。您可能还应该根据false行来了解JS世界中的true!!response && response.length ? true : false;是什么–也许我在这里遗漏了一些东西。

答案 1 :(得分:-1)

问题是您使用的是@IBOutlet private weak var cartView: UIView! { didSet { updateCartViewVisibility() } } var items = 0 { didSet{ updateCartViewVisibility() } } private func updateCartViewVisibility() { guard cartView != nil else { return } cartView.isHidden = items == .zero } 错误。

async / await适用于诺言-您给诺言,然后等待它解决/拒绝。如果您不给它一个诺言,就像给它一个立即解决的诺言。

您的await函数不会兑现​​承诺,因此发生的是该代码:

setDashboard

实际上可以立即解析,但是await Promise.all([ this.setDashboard("p1"), this.setDashboard("p2"), ]); 函数直到setDashboard才执行。为什么?因为它们被定义为异步,这使它们进入事件循环。然后出现在this.navigateToDashboards();中,但是它立即解析,因为内部的函数不会返回promise(嗯,它确实可以,因为它是异步的,但是就像写await作为第一行一样,因此return promise.resolve()不执行任何操作,仅将函数置于事件循环中)-并且代码以同步方式继续执行,直到到达函数末尾为止(例如,执行await,然后进入事件循环并执行this.navigateToDashboards();函数。

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

要正确使用async / await,请确保您的fetchUserAccounts()函数返回一个Promise,例如:

async

关于fetchUserAccount:

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

请注意,您现在必须使用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