如何使用 async/await 访问 Axios 返回的数据

How to access Data returning by Axios with async/await

我有两个函数使用 Axios 向 API 发出数据请求。在这些功能中,我还 return API 收到的响应。这两个函数都使用 async/await。根据我的理解,由于 Axios return 是一个承诺,我必须等待函数调用来解压缩承诺并检索数据。我是否错误地调用了这些函数?目标是使用这些函数 returned 的值来呈现 React-Leaflet 组件。但是,React 似乎将值读取为 null。我的假设是,当在组件内调用函数时,Promise 被 returned 而不是值,即使我正在使用 await 调用函数。下面是我到目前为止的代码...

import { MapContainer, TileLayer, Marker, Popup, Circle } from 'react-leaflet';
import mockData from './testData/MOCK_DATA.json'
import axios from 'axios';
import outageData from './testData/outageData.json'

const fillBlueOptions = { fillColor: 'blue' };

async function convertAddressLat(location){//uses the geocodify api to get lat and long of an address
        const resp = await axios.get('https://api.geocodify.com/v2/geocode/json?api_key=mykey&q=' + location.outage_street+ ', ' + location.outage_city+ ', Michigan, USA');
        return Number(resp.data.response.bbox[1]);

}

async function convertAddressLong(location){
    const resp = await axios.get('https://api.geocodify.com/v2/geocode/json?api_key=mykey&q=' + location.outage_street+ ', ' + location.outage_city+ ', Michigan, USA');
    return Number(resp.data.response.bbox[2]);
}

/// This returns the actual value I am looking to pass into the react component
(async function(){
    let val = await convertAddressLat(outageData.outages[6]);
    console.log("Inside function 1: "+val);
})();

//this is still returning a promise. I have tried returning the await and also the method below
console.log("inside function 2: "+(async function(){
    let x = await convertAddressLat(outageData.outages[6]);
    return x;
})());

function OutageMap() { //This is where the map page will be rendered.
    return (
        <MapContainer center={[38.89, -77.059]} zoom={13} scrollWheelZoom={true}>
            <TileLayer
                attribution='&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
                url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
            />

            {outageData.outages.map(mock => (
                <Circle center={[
                    (async function(){
                        let lat = await convertAddressLat(mock);
                        return lat;})(), 
                    (async function(){
                        let long = await convertAddressLong(mock);
                        return long;})()
                    ]} 
                    pathOptions={fillBlueOptions} radius={200}>
                    <Popup>{mock.description}</Popup>
                </Circle>
            ))}
        </MapContainer>
    );
  }
  
  export default OutageMap;

我已经参考了这个 post How to return the response from an asynchronous call 关于如何展开承诺,但我很困惑如何在 React 组件中调用该函数。

将这些函数放在组件中。删除 async/await 并将其替换为 then, catch 块。例如,如果我们有异步函数 'fetch' 返回它看起来像的值:

fetch().then(response => {
   do sth
}).catch(err => {
   console.log(err);
})

调用

中的函数
useEffect(() => {
    fetch().then().catch()
},[]) 

勾。如果您传递空的依赖项列表,它将表现得像 componentDidMount。在 then 块中,将返回值分配给状态(它将重新渲染组件)。

useEffect(() => {
    fetch().then(res => {
        setState(res.data);
    }).catch()
},[]) 

在视图中检查您的状态是否具有值:如果不呈现 'No values or sth'。您还可以添加加载反馈。在调用异步函数之前将加载状态设置为 true,并在 then/catch 块中设置为 false。

useEffect(() => {
    setLoading(true);
    fetch().then(res => {
        setState(res.data);
        setLoading(false);
    }).catch(err => {
        setLoading(false);
    })
},[]) 

然后你可以根据加载状态提供一些反馈。

据我所知,您目前正在使用功能组件。因此,您可以在该函数中使用 'useEffect' 挂钩来调用 api 例如

function myFuncComponent() {
  const [data,setData] = useState();
  useEffect(async () => {
   const { data } = await axios.get('my url');
   setData(data);
  })
}

如果你想在 React 组件中调用这些异步调用,你只需定义一个状态变量,你的组件会更改它,你将使用异步函数或在 useEffect 中处理更改。

async 函数总是 return 一个 Promise。因此,在此块中,您正在等待 convertAddressLat Promise,但匿名内联函数也 return 是一个 Promise。

center={[
  (async function(){
    let lat = await convertAddressLat(mock);
    return lat;})()

呈现异步加载数据的一种常见策略是在 useEffect 挂钩中进行提取,一旦 Promise 被解析,该挂钩就会设置状态:

function OutageIndicator ({ outage }) {
    const [coords, setCoords] = useState();

    useEffect(() => {
        async function resolveLocation() {
          const resp = await axios.get( ... );
          const [lat, lng] = resp.data.response.bbox;
          setCoords({ lat, lng })
        }

        resolveLocation();
    }, [outage]);

    return !coords ? "Loading" : (
        <Circle center={[coords.lat, coords.lng]} />
    )
}

function OutageMap () {
    return (
        <MapContainer center={[38.89, -77.059]} zoom={13} scrollWheelZoom={true}>
            {outageData.outages.map(outage => (
                <OutageIndicator outage={outage} />
            )}
        </MapContainer>
    )
}