簡體   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