同时执行两项功能

时间:2019-10-16 09:44:08

标签: javascript

我有一个函数,该函数在调用该函数时刷新组件的数据。目前,它一次仅适用于一个组件。但是我想一次刷新两个组件。这是我的刷新功能:

   fetchDataByName = name => {
        const { retrievedData } = this.state;
        const { fetcher } = this.props;
        const fetch = _.find(fetcher, { name });

        if (typeof fetch === "undefined") {
          throw new Error(`Fetch with ${name} cannot be found in fetcher`);
        }

        this.fetchData(fetch, (error, data) => {
          retrievedData[name] = data;
          this._isMounted && this.setState({ retrievedData });
        });
      };

我的函数被这样调用:

refresh("meetingTypes");

当它作为道具传递给我的组件时:

return (
        <Component
          {...retrievedData}
          {...componentProps}
          refresh={this.fetchDataByName}
        />
      );

我尝试将多个组件名称作为这样的数组传递:

const args = ['meetingTypes', 'exampleMeetingTypes'];
refresh(args);

然后检查我的fetchDataByName函数是否name是一个数组,并循环遍历该数组以获取数据。但是随后该函数仍然彼此执行而不是同时执行。所以我的问题是:

  

实现此目标的最佳方法是什么?   函数立即执行,而不是先刷新meetingTypes   然后是exampleMeetingTypes?

我应该使用async/await还是有更好的选择?

fetchData函数:

fetchData = (fetch, callback) => {
    const { componentProps } = this.props;
    let { route, params = [] } = fetch;
    let fetchData = true;

    // if fetcher url contains params and the param can be found
    // in the component props, they should be replaced.
    _.each(params, param => {
      if (componentProps[param]) {
        route = route.replace(`:${param}`, componentProps[param]);
      } else {
        fetchData = false; // don't fetch data for this entry as the params are not given
      }
    });

    if (fetchData) {
      axios
        .get(route)
        .then(({ data }) => {
          if (this.isMounted) {
            callback(null, data);
          }
        })
        .catch(error => {
          if (error.response.status == 403) {
            this._isMounted && this.setState({ errorCode: 403 });
            setMessage({
              text: "Unauthorized",
              type: "error"
            });
          }

          if (error.response.status == 401) {
            this._isMounted && this.setState({ errorCode: 401 });
            window.location.href = "/login";
          }

          if (error.response.status != 403) {
            console.error("Your backend is failing.", error);
          }
          callback(error, null);
        });
    } else {
      callback(null, null);
    }
  };

1 个答案:

答案 0 :(得分:1)

我假设fetchData异步工作(ajax或类似的)。要并行刷新数据的两个方面,只需进行两次调用而不是一次:

refresh("meetingTypes");
refresh("exampleMeetingTypes");

两个ajax调用或任何将并行运行的调用,每个调用都会在完成时更新组件。 但是:请参见下面的“旁注”,fetchDataByName有问题。

如果要避免两次更新组件,则必须更新fetchDataByName以接受多个名称或返回结果的承诺(或类似结果),而不是直接更新组件,因此,呼叫者可以进行多个呼叫,并等待两个结果,然后再进行更新。


旁注:fetchDataByName的这一方面令人怀疑:

fetchDataByName = name => {
  const { retrievedData } = this.state;  // <=============================
  const { fetcher } = this.props;
  const fetch = _.find(fetcher, { name });

  if (typeof fetch === "undefined") {
    throw new Error(`Fetch with ${name} cannot be found in fetcher`);
  }

  this.fetchData(fetch, (error, data) => {
    retrievedData[name] = data;          // <=============================
    this._isMounted && this.setState({ retrievedData });
  });
};

有两个问题:

  1. 它会直接更新状态下存储的对象,这是您绝对不能使用React进行的操作。
  2. 它将整个retrievedData对象替换为很旧的对象。

相反:

fetchDataByName = name => {
  // *** No `retrievedData` here
  const { fetcher } = this.props;
  const fetch = _.find(fetcher, { name });

  if (typeof fetch === "undefined") {
    throw new Error(`Fetch with ${name} cannot be found in fetcher`);
  }

  this.fetchData(fetch, (error, data) => {
    if (this._isMounted) {                                  // ***
      this.setState(({retrievedData}) => (                  // ***
        { retrievedData: {...retrievedData, [name]: data} } // ***
      );                                                    // ***
    }                                                       // ***
  });
};

这将消除对象随传播的就地突变,并通过使用retrievedData的回调版本来使用setState的最新版本。