将两个反应 API 链接在一起,其中一个的输出进入第二个的输入。使用 Axios/Async

Posted

技术标签:

【中文标题】将两个反应 API 链接在一起,其中一个的输出进入第二个的输入。使用 Axios/Async【英文标题】:Chaining two react APIs together where the output of one goes into the input of the second. Uses Axios/Async 【发布时间】:2019-05-28 05:48:57 【问题描述】:

使用反应。

我是一个应用程序,它获取已由搜索栏提交的数据并返回一个 ID 列表。我想获取这些 id 并通过另一个 api 传递它。但是,我不确定如何执行此操作。我查看了*** 上的其他一些页面,例如this 和this。第一个有点模糊,第二个有独立的 api 调用,按顺序运行。

这是我的代码:

import React from 'react'
import api1 from '../api/api1'

import SearchBar from './SearchBar'

class App extends React.Component 
    state =  cards: [],  new_cards: []; 

    onSearchSubmit = async (term) => 
    const response = await api1.get("api/decks/" + term)
    this.setState( cards: response.data.data.cards, )
     

  render () 
    return (<div className='ui container'>
      <SearchBar onSubmit=this.onSearchSubmit />
      /* <CardList cards=this.state.cards /> */
    </div>)
  

export default App

我的代码将采用第一个 api 并将输出(包含 36 个项目的列表)传递给组件 CardList。然而,这个列表并不完整,它需要是一个列表列表(你可以看出我是从 python 过来的)。我需要首先调用一个不同的 api(在我的机器上仍然是本地的),获取其余数据,然后将一个新列表(36 个列表)传递给组件 CardList。第二个 api 本身就可以正常工作。我很难将两者结合起来。

这是我的想法,但它不起作用。 1)新建函数getCardStats 2) 使用 map 函数遍历列表一并运行 api 调用。 3) 将步骤 2) 的输出附加到新列表 4) 返回新列表 5) 将新列表传入 CardList

第一个列表中有 36 个项目,因此下一个 api 需要调用 36 次。我不知道做那么多/很少的后果是什么。我们是否需要放置一些等待所有 36 个完成的东西,或者我们可以并行执行它们吗?

import React from 'react'
import api1 from '../api/api1'
import api2 from '../api/api2'

import SearchBar from './SearchBar'

class App extends React.Component 
    state =  cards: [] ; 

    onSearchSubmit = async (term) => 
    const response = await api1.get("api/decks/" + term)

    this.setState( cards: response.data.. )
    this.getCardStats(this.state.cards)
            

    getCardStats = async (cards)=> 
      console.log('we are here')
      console.log(cards)
      const response = props.cards.map(card => 
          return await api2.get("api/cards/" + card)
      )
    
    console.log('finished')
    console.log(response)
    this.setState( new_cards: response.data.data.cards )

  render () 
    return (<div className='ui container'>
      <SearchBar onSubmit=this.onSearchSubmit />
      /* <CardList cards=this.state.new_cards /> */
    </div>)
  

export default App

想法?

【问题讨论】:

这已经是一个淫秽的电话量了......当36变成360时会发生什么......? 所以,我负责 36 个(或多或少),所以我知道它永远不会超过或低于那个。而且我正在寻找一种方法来进行一次调用,但我也很想知道如何做到这一点(比如说如果不是 36 而是 2)。 【参考方案1】:

Axios 调用返回 Promises,我假设您的 API 函数使用它。似乎您被困在如何使用它们上,即将它们连接在一起,或者发射一堆并等待它们全部解决。希望我可以解释如何在没有保存状态的中间步骤的情况下执行此操作。

import React from 'react'
import api1 from '../api/api1'
import api2 from '../api/api2'

import SearchBar from './SearchBar'

class App extends React.Component 
  state =  cards: null ; 

  onSearchSubmit = term => 
    api1.get("api/decks/" + term) // returns a resolved promise, which is 'then'-able
      .then(cards => 
        // now we can setup our next API call
        // create an array of them and use Promise.all()

        const cardRequests = cards.map(card => api2.get(`api/cards/$card`));
        return Promise.all(cardRequests); // This Promise resolves when all individual promise resolve, or rejects if any single one rejects.
      )
      .then(allCardsResults => 
        // Here we now have an array of resolved API values
        // Map, flatten, reduce, etc.. to whatever we need 
        // in state for the CardList

        const reducedCards = allCardsResults.reduce((acc, cardResult) => acc.concat(cardResult), []);

        this.setState(
          cards: reducedCards,
        );
      )
      .catch(error => 
        // do any clean up or state management here should
        // any errors or promises get rejected
      );
          

  render () 
    const  cards  = this.state;
    return (
      <div className='ui container'>
        <SearchBar onSubmit=this.onSearchSubmit />
         cards && <CardList cards=cards /> // Only render if `cards` is truthy
      </div>
    )
  

export default App

工作示例

const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0];

new Promise((resolve, reject) => resolve(numbers))
.then(result => 
  console.log(`Initial numbers array: $result`);
  const promiseArray = result.map(key => 
    return Promise.resolve( key, numbers );
  );
  return Promise.all(promiseArray);
)
.then(moreNumbers => 
  console.log(`More numbers: $JSON.stringify(moreNumbers)`);
  const reducedNumbers = moreNumbers.reduce((acc, mn) => acc.concat(mn.numbers), []);
  return Promise.resolve(reducedNumbers);
)
.then(finalNumberArray => console.log(`Final number array: $finalNumberArray`));

【讨论】:

这很棒。我要把它和 console.logging 的东西扔掉,这样我就可以理解了。我收到此错误cards.map is not a function 谢谢。尝试记录类型 console.log(typeof cards);,您的第一个 API 可能不会返回数组。如果你真的很欣赏我的回答,你能接受吗?

以上是关于将两个反应 API 链接在一起,其中一个的输出进入第二个的输入。使用 Axios/Async的主要内容,如果未能解决你的问题,请参考以下文章

将两个 matplotlib 滑块链接在一起

我可以将反应路由器链接与 CardActionArea 一起使用吗?

如何将上下文 api 与反应路由器 v4 一起使用?

反应帐户激活

在本机反应中获取返回旧数据的 API

《程序员自我修养》阅读笔记-静态链接