代码之家  ›  专栏  ›  技术社区  ›  Darren

按正确顺序加载componentDidMount中的异步/等待

  •  2
  • Darren  · 技术社区  · 7 年前

    我在以正确的顺序加载多个函数时遇到一些问题。从下面的代码中,第一个和第二个函数用于获取 companyID companyReference 并且不依赖于彼此。

    第三个功能需要 state 由第一个和第二个函数设置,以实现获取 companyName .

    async componentDidMount() {
        const a = await this.companyIdParams();
        const b = await this.getCompanyReference();
        const c = await this.getCompanyName();
        a;
        b;
        c;
      }
    
      componentWillUnmount() {
        this.isCancelled = true;
      }
    
      companyIdParams = () => {
        const urlString = location.href;
        const company = urlString
          .split('/')
          .filter(Boolean)
          .pop();
        !this.isCancelled &&
          this.setState({
            companyID: company
          });
      };
    
      getCompanyReference = () => {
        const { firebase, authUser } = this.props;
        const uid = authUser.uid;
        const getUser = firebase.user(uid);
        getUser.onSnapshot(doc => {
          !this.isCancelled &&
            this.setState({
              companyReference: doc.data().companyReference
            });
        });
      };
    
      getCompanyName = () => {
        const { firebase } = this.props;
        const { companyID, companyReference } = this.state;
        const cid = companyID;
        if (companyReference.includes(cid)) {
          const getCompany = firebase.company(cid);
          getCompany.onSnapshot(doc => {
            !this.isCancelled &&
              this.setState({
                companyName: doc.data().companyName,
                loading: false
              });
          });
        } else if (cid !== null && !companyReference.includes(cid)) {
          navigate(ROUTES.INDEX);
        }
      };
    

    componentDidMount ?

    2 回复  |  直到 7 年前
        1
  •  6
  •   David Táboas    7 年前

    setState是异步的,因此无法确定何时以同步方式更新状态。

    1) 我建议您不要将componentDidMount与async一起使用,因为此方法属于react生命周期。

    componentDidMount() {
      this.fetchData();
    }
    
    fetchData = async () => {
      const a = await this.companyIdParams();
      const b = await this.getCompanyReference();
      const c = await this.getCompanyName();
    }
    
    

    2)

    如果您需要等待,我会在设置状态完成时返回一个承诺;

    companyIdParams = () => {
      return new Promise(resolve => {
        const urlString = location.href;
        const company = urlString
          .split('/')
          .filter(Boolean)
          .pop();
        !this.isCancelled &&
          this.setState({
            companyID: company
          }, () => { resolve() });
      });
    };
    

    getCompanyReference也一样:

    getCompanyReference = () => {
      return new Promise(resolve => {
        const { firebase, authUser } = this.props;
        const uid = authUser.uid;
        const getUser = firebase.user(uid);
        getUser.onSnapshot(doc => {
          !this.isCancelled &&
            this.setState({
              companyReference: doc.data().companyReference
            }, () => { resolve() });
        });
      });
    };
    

    如果要并行化承诺,可以将以前的代码更改为:

    const [a, b] = await Promise.all([
      await this.companyIdParams(),
      await this.getCompanyReference()
    ]);
    

    const [a, b] = .....
    const c = this.getCompanyName()
    

    编辑:要点不是要遵循的步骤

        2
  •  2
  •   Sushanth --    7 年前

    由于最后一个api调用取决于前两个api调用的响应,因此使用 Promise.all

    async componentDidMount() {
        let [a, c] = await Promise.all([
            this.companyIdParams(),
            this.getCompanyReference()
        ]);
    
        const c = await this.getCompanyName();
    }