【问题标题】:How to call two async functions one after the other?如何一个接一个地调用两个异步函数?
【发布时间】:2020-11-15 02:44:51
【问题描述】:

我是 JavaScript 的新手,目前在 React Native 中使用 async/await。我有两个异步函数getAsyncLocationgetParkinggetAsyncLocation 从设备以及路由参数(从另一个屏幕路由时获得)获取位置。 getParking 使用状态 - mapRegion - 由 getAsyncLocation 分配来查找相关结果。

但是,当我一个接一个地运行它们时,我得到了:-

[Unhandled promise rejection: TypeError: null is not an object (evaluating 'mapRegion.latitude')]

我有以下代码:-

const [mapRegion, setmapRegion] = useState(null);

handleMapRegionChange = (mapRegion) => setmapRegion({ mapRegion });

  const handleCenterChange = (lat, lng) => setmapRegion({
    latitude: lat,
    longitude: lng,
    latitudeDelta: 0.0922,
    longitudeDelta: 0.0421,
  })

async function getAsyncLocation() {
    if (route.params) { // obtained from some other screen
      handleCenterChange(route.params.lat, route.params.lng);
      console.log("route params for location ", mapRegion.latitude, mapRegion.longitude);
    }
    else {
      const { status, permissions } = await Permissions.askAsync(
        Permissions.LOCATION
      );

      if (status === "granted") {
        sethasLocationPermission(true);
        let location = await Location.getCurrentPositionAsync({});
        setlocationResult(JSON.stringify(location));
        handleCenterChange(location.coords.latitude, location.coords.longitude);
      } else {
        alert("Location permission denied");
      }
    }
  }

  async function getParkings() {
    console.log("get parking runing")
    console.log("get parkig ", mapRegion.latitude, ", ", mapRegion.longitude);
    await axios.get(`http://${MyIp}:8080/booking/findParking`, {
      params: {
        lat: mapRegion.latitude,
        lng: mapRegion.longitude,
        rad: 10
      },
      headers: {
        'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
      }
    })
      .then((response) => {
        let parkingSpace = response.data;
        let parking = []
        for (let i = 0; i < parkingSpace.length; i++) {
          parking.push({
            spaceId: parkingSpace[i]._id,
            ownerId: parkingSpace[i].owner,
            location:
              { latitude: parkingSpace[i].latitude, longitude: parkingSpace[i].longitude }
          })
        }
        console.log(parking)
        setSpace(parking);
      })
      .catch((err) => {
        console.log(err)
      })
  }

  async function getData() {
    await getAsyncLocation();
    await getParkings();
  }

  useEffect(() => {
    getData();
  }, []);

我曾尝试在各种博客和 stackoverflow 问题中搜索它,但无法解决。任何提示将不胜感激。

【问题讨论】:

  • 一个异步函数只能等待一个promise,所以为了在getData()中使用await关键字和await getAsyncLocation()和await getParkings(),确保这些函数确实返回一个承诺。例如,返回 axios.get(...)。
  • 同意@RicardoAgra

标签: javascript react-native async-await


【解决方案1】:

您可以使用另一个 useEffect 挂钩来监视 mapRegion 状态是否已更改。 (您可以在您的应用中拥有任意数量的 useEffect 挂钩)

useEffect(() => {
    getAsyncLocation(); 
  }, []); // [] without any args, this will be called only once. We want to get device location only once

  useEffect(() => {
    getParkings();
  }, [mapRegion]) // since we have passed mapRegion as arg therefore it would be called whenever mapRegion is updated

【讨论】:

    【解决方案2】:

    Ciao,为了在getParkings 之前执行getAsyncLocation,你必须使用Promise。但是还有另一个问题:即使您顺序运行getAsyncLocationgetParkings,也不能保证在getParkingsmapRegion 具有getAsyncLocation 设置的值(因为Hooks 是异步的!)。那么如何解决你的问题呢?你有几个选择。一个是像这样使用 2 useEffect:

    useEffect(() => {
       getAsyncLocation(); 
    }, []);
    
    useEffect(() => {
       getParkings();
    }, [mapRegion]);
    

    这种方法有两个问题:

    1. 每次加载 useEffects 所在的组件时,都会触发第一个 useEffect(也许您不希望这样)。
    2. 每次mapRegion 更改他的值时,都会触发第二个useEffect(也许你不希望这样)。

    所以,正如我所说,我建议采用 Promise 方法,但传递 getParkings 由于 getAsyncLocation 而需要的值。你的代码变成:

    getAsyncLocation

    async function getAsyncLocation() {
    return new Promise(resolve => {
       let result = {lat: -1, lng: -1};
       if (route.params) { // obtained from some other screen
         handleCenterChange(route.params.lat, route.params.lng);
         console.log("route params for location ", mapRegion.latitude, mapRegion.longitude);
         result.lat = route.params.lat;
         result.lng = route.params.lng;
         resolve(result);
         return;
       }
       else {
         const { status, permissions } = await Permissions.askAsync(
           Permissions.LOCATION
        );
    
         if (status === "granted") {
           sethasLocationPermission(true);
           let location = await Location.getCurrentPositionAsync({});
           setlocationResult(JSON.stringify(location));
           handleCenterChange(location.coords.latitude, location.coords.longitude);
           result.lat = location.coords.latitude;
           result.lng = location.coords.longitude;
           resolve(result);
           return;
         } else {
           alert("Location permission denied");
         }
       }
       resolve(result);
    });
    }
    

    getParkings

    async function getParkings(myMapRegion) {
     return new Promise(resolve => {
       console.log("get parking runing")
       console.log("get parkig ", myMapRegion.lat, ", ", myMapRegion.lng);
       await axios.get(`http://${MyIp}:8080/booking/findParking`, {
         params: {
           lat: myMapRegion.lat,
           lng: myMapRegion.lng,
           rad: 10
         },
         headers: {
           'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
         }
       })
         .then((response) => {
           let parkingSpace = response.data;
           let parking = []
           for (let i = 0; i < parkingSpace.length; i++) {
             parking.push({
               spaceId: parkingSpace[i]._id,
               ownerId: parkingSpace[i].owner,
               location:
                 { latitude: parkingSpace[i].latitude, longitude: parkingSpace[i].longitude }
             })
           }
           console.log(parking)
           setSpace(parking);
         })
         .catch((err) => {
           console.log(err)
         })
         resolve();
      });
     }
    

    获取数据

    async function getData() {
       let myMapRegion = await getAsyncLocation();
       await getParkings(myMapRegion);
    }
    

    【讨论】:

      猜你喜欢
      • 2020-09-17
      • 2020-07-17
      • 1970-01-01
      • 2022-11-22
      • 1970-01-01
      • 2019-05-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多