开发者问题收集

反应钩子中的异步等待承诺拒绝

2022-09-10
483

我想我误解了异步等待的工作方式,尤其是使用另一个文件中的函数时。因此,我想使用 API 上的 axios 调用从经度和纬度获取地址

import { getAddressFromLongLat } from "../hooks/queries-hook";
import React, { useEffect, useState } from "react";

const Component = (props) => {
  const [address, setAddress] = useState(null);
  useEffect(() => {
    const fetchFromLongLat = async () => {
      if (props.coords) {
        const response = await getAddressFromLongLat(props.coords);
        console.log("response from nominatim " + JSON.stringify(response, null, 4));
        setAddress(response);
      }
    };
    fetchFromLongLat();
  }, []);

  return <></>;
};

然后进入 queries-hook.js

import axios from "axios";

export const getAddressFromLongLat = async (coords) => {
  const URL = "http://nominatim.openstreetmap.org/reverse";
  const response = await axios.get(URL, {
    params: {
      format: "json",
      lat: coords.lat,
      lon: coords.long
    },
    headers: {
      "Content-Type": "application/json; charset=UTF-8"
    }
  });
  return {
    street: response.address.road + " " + response.address.house_number,
    cp: response.address.postcode,
    city: response.address.town,
    country: response.address.country_code.toUpperCase()
  };
};

有人可以向我解释如何正确编写带有这些异步等待的代码以避免出现错误吗:

Possible Unhandled Promise Rejection (id: 0): TypeError: undefined is not an object (evaluating 'response.address.road')

3个回答

问题是由于 response 不包含 address 属性和所有其余属性。但是 response.data 包含。

您必须在 return 之前添加 console.log(response); 才能解决此问题。 { "lat": 50.806002951249546, "long": 4.410705976188183 } 的输出将为:

{
  "data": {
    "place_id": 113461740,
    "licence": "Data © OpenStreetMap contributors, ODbL 1.0. https://osm.org/copyright",
    "osm_type": "way",
    "osm_id": 30994925,
    "lat": "50.8066154",
    "lon": "4.410838323013642",
    "display_name": "Parc sportif des Trois Tilleuls, Avenue Léopold Wiener - Léopold Wienerlaan, Le Triangle - De Driehoek, Ватермаль-Буафор, Брюссельский столичный регион, 1170, Бельгия",
    "address": {
      "leisure": "Parc sportif des Trois Tilleuls",
      "road": "Avenue Léopold Wiener - Léopold Wienerlaan",
      "neighbourhood": "Le Triangle - De Driehoek",
      "town": "Ватермаль-Буафор",
      "county": "Брюссельский столичный регион",
      "region": "Брюссельский столичный регион",
      "ISO3166-2-lvl4": "BE-BRU",
      "postcode": "1170",
      "country": "Бельгия",
      "country_code": "be"
    },
    "boundingbox": [
      "50.8042107",
      "50.80902",
      "4.4079878",
      "4.4130556"
    ]
  },
  "status": 200,
  "statusText": "",
  ...
  (cutted)
}

因此修复函数:

const getAddressFromLongLat = async (coords) => {
  // switched to HTTPS here also
  const URL = "https://nominatim.openstreetmap.org/reverse";
  const response = await axios.get(URL, {
    params: {
      format: "json",
      lat: coords.lat,
      lon: coords.long
    },
    headers: {
      "Content-Type": "application/json; charset=UTF-8"
    }
  });
  const { data } = response; // equal to const data = response.data
  return {
    street: data.address.road + " " + data.address.house_number,
    cp: data.address.postcode,
    city: data.address.town,
    country: data.address.country_code.toUpperCase()
  };
};
Sergey Sosunov
2022-09-10
import axios from 'axios';
import React from 'react'
import { useEffect } from 'react';
import { useState } from 'react';

const Try = () => {

    const [address, setAddress] = useState(null);

    const getAddressFromLongLat = async () => {
        const URL = "http://nominatim.openstreetmap.org/reverse";
        const response = await axios.get(URL, {
            params: {
                format: "json",
                lat: 36.884804,
                lon: 30.704044
            },
            headers: {
                "Content-Type": "application/json; charset=UTF-8"
            }
        });
        const { data } = response; **// There is your mistake.**
        return {

            street: data.address.road + " " + data.address.house_number,
            cp: data.address.postcode,
            city: data.address.town,
            country: data.address.country_code.toUpperCase()
        };
    };

    useEffect(() => {
        const fetchFromLongLat = async () => {
            if (1 === 1) {
                const response = await getAddressFromLongLat();
                console.log("response from nominatim " + JSON.stringify(response, null, 4));
                setAddress(response);
            }
        };
        fetchFromLongLat();
    }, []);

    console.log(address)
    return (
        <div>try</div>
    )
}

export default Try
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.27.2/axios.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
Ramazan Ertan
2022-09-10

我不确定,但可能您不需要在第二个函数中使用 async...await。这就像 tako 里面还有 tako。但您只需要在一个 tako 铃铛里放两个 tako。

Gibloor
2022-09-10