繁体   English   中英

存储来自 Axios Promise 的数据以供多种用途

[英]Storing data from Axios Promise for multiple uses

我在 express 中创建了一个端点来处理获取请求。 从反应组件,我使用 axios 向所述端点发出 get 请求。 我想将数据存储在我的 Component 类的对象中,以便可以多次访问(onComponentDidLoad、多个 onClick 事件处理程序等)。 有没有办法将数据存储在 axios 承诺之外,和/或保留承诺,以便我可以在不履行承诺的情况下进行多次 .then 调用?

我尝试使用 setState(),返回承诺,并从 get 请求返回实际数据。

这是我现在所拥有的:

constructor {
  super();
  this.myData = [];
  
  this.getData = this.getData.bind(this);
  this.storeData = this.storeData.bind(this);
  this.showData = this.showData.bind(this);
}

// Store data
storeData = (data) => {this.myData.push(data)};

// Get data from API
getData() {
    axios
        .get('/someEndpoint')
        .then(response => {
            let body = response['data'];

            if(body) {
                this.storeData(body);
            }
        })
        .catch(function(error) {
            console.log(error);
        });
}

showData() {
    console.log(this.myData.length); // Always results in '0'
}

componentDidMount = () => {
    this.getData();   // Get data
    this.showData();   // Show Data
}
    
render() {
  return(
      <Button onClick={this.showData}> Show Data </Button>
  );
}

编辑我的问题不正确,存储承诺然后进行多个 .then 调用有效。 我试的时候格式不对。

如果您只是将承诺存储在本地并将其作为承诺访问它应该可以正常工作。

getData() {
  // if request has already been made then just return the previous request.
  this.data = this.data || axios.get(url)
  .then( response => response.data)
  .catch(console.log)
  return this.data
}

showData() {
  this.getData().then(d => console.log('my data is', data));
}

此代码将无法正常工作,因为您试图在不等待解析的情况下显示数据:

componentDidMount = () => {
    this.getData();
    this.showData();
}

正如您在原始帖子中暗示的那样,您需要从 Promise 中提取数据,而无法以同步方式执行此操作。 您可以做的第一件事就是简单地存储原始 Promise 并在需要时访问它 - 可以多次then() ed Promises:

class C extends React.Component {
  state = {
    promise: Promise.reject("not yet ready")
  };

  showData = async () => {
    // You can now re-use this.state.promise.
    // The caveat here is that you might potentially wait forever for a promise to resolve.
    console.log(await this.state.promise);
  }

  componentDidMount() {
    const t = fetchData();
    this.setState({ promise: t });
    // Take care not to re-assign here this.state.promise here, as otherwise
    // subsequent calls to t.then() will have the return value of showData() (undefined)
    // instead of the data you want.
    t.then(() => this.showData());
  }
  
  render() {
    const handleClick = () => {
      this.showData();
    };

    return <button onClick={handleClick}>Click Me</button>;
  }
}

另一种方法是通过将异步完全限制在 fetchData() 函数中来尝试使您的组件尽可能同步,这可能会使您的组件更容易推理:

class C extends React.Component {
  state = {
    status: "pending",
    data: undefined
  };

  async fetchData(abortSignal) {
    this.setState({ status: "pending" });
    try {
      const response = await fetch(..., { signal: abortSignal });
      const data = await response.json();
      this.setState({ data: data, status: "ok" });
    } catch (err) {
      this.setState({ error: err, status: "error" });
    } finally {
      this.setState({ status: "pending" });
    }
  }

  showData() {
    // Note how we now do not need to pollute showData() with asyncrony
    switch (this.state.status) {
      case "pending":
        ...
      case "ok":
        console.log(this.state.data);
      case "error":
        ...
    }
  }

  componentDidMount() {
    // Using an instance property is analogous to using a ref in React Hooks.
    // We don't want this to be state because we don't want the component to update when the abort controller changes.
    this.abortCtrl = new AbortController();
    this.fetchData(this.abortCtrl.signal);
  }

  componentDidUnmount() {
    this.abortCtrl.abort();
  }

  render() {
    return <button onClick={() => this.showData()}>Click Me</button>
  }
}

暂无
暂无

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

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