You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React中如何在等待异步函数返回时暂停for循环?

问题

遍历数组时希望按顺序显示变量dist,但遍历过程中该变量输出顺序混乱。回调函数内的for循环执行顺序正常,但外层第一个for循环输出无序。已尝试将包含两个循环的函数设为async,但问题未解决。相关代码如下:

async function getStations(pBounds){
    
    let gasMarkers = []
    var currTankSize = 0
    if (CurrentSize === "TFive"){
      currTankSize = TankSize*.25
      console.log("currTSIZE: " + currTankSize)
    } 
    else if(CurrentSize === "Fifty"){
      currTankSize = TankSize *.5
      console.log("currTSIZE: " + currTankSize)
    }
    else if(CurrentSize === "SFive"){
      currTankSize = TankSize*.75
      console.log("currTSIZE: " + currTankSize)
    }
    else{ currTankSize = TankSize
      console.log("currTSIZE: " + currTankSize)}
    distCoords.push([waypoints[0][0], waypoints[0][1]])
    var distTrack = 0
    
    const service = new google.maps.places.PlacesService(map)
    const searchPromises = [];
    for (let i = 0; i < waypoints.length; i+=40){
      service.nearbySearch({
        location:{ lat: waypoints[i][0], lng:waypoints[i][1]},
        radius: '20000',
        type: ['gas_station']
      },callback)

    
    
      console.log("i before the second for loop: " + i)

      async function callback(results, status){
        if(status === google.maps.places.PlacesServiceStatus.OK){
          for (var j = 0; j < results.length; j++){
            if(google.maps.geometry.poly.containsLocation(results[j].geometry.location,pBounds) === true){
              //console.log("GEO: " + results[j].geometry.location.lat())
              
              let dist = await distanceCalc(distCoords[distTrack][0], distCoords[distTrack][1], results[j].geometry.location.lat(), results[j].geometry.location.lng() )
              dist = dist / Mpg
              currTankSize = currTankSize - dist
              var gasLvl = currTankSize/TankSize
              console.log("i: " + i + " j: " + j+ " Gas: " + gasLvl)
              
              //console.log("LEVEL: " + gasLvl)
              gasLvl = Math.round(gasLvl *10) / 10
              //console.log(results[j]['vicinity'])
              //console.log(results[j]['plus_code']['compound_code'])
              if (gasLvl <= .5){
                distCoords.push([results[j].geometry.location.lat(), results[j].geometry.location.lng()])
                distTrack+=1
                currTankSize = TankSize
                gasMarkers.push(new google.maps.Marker({
                  position: results[j].geometry.location, map, 
                  title: results[j]['name']
                }))

                if(!setGas.has(results[j]['vicinity'])){
                  var price = getGasStationInfo(results[j].geometry.location.lat(), results[j].geometry.location.lng())
                }

                var info = {
                  name: results[j]['name'],
                  vicinity: results[j]['vicinity'],
                  price: await price
                }
                if(!setGas.has(results[j]['vicinity'])){
                  GasInformation.push(info);
                  setGas.add(results[j]['vicinity'])
                  console.log("INLOOP:" + GasInformation);
                  GasSet = Array.from(new Set(GasInformation))
                  setValueArray(GasSet)
                }
                
                
                
              }
            }
          }
        }
      }
    }
    setGasMarkerArray(gasMarkers)
    
    //getGasStationInfo()
    //console.log("ARRAY: " + GasInformation )
    //console.log("SET" + ValueArray);
    //console.log("Value in the array: "+ValueArray.length);
    
  }
async function distanceCalc(lat1, long1, lat2, long2){
    const pt1 = {lat: lat1, lng: long1}
    const pt2 = {lat: lat2, lng: long2}

    let distanceService = new google.maps.DirectionsService()
    const dist = await Promise.resolve(distanceService.route({
      origin: pt1,
      destination: pt2, 
      travelMode: google.maps.TravelMode.DRIVING}))
    
    var miles = dist.routes[0].legs[0].distance.value

    miles = miles/1609.34
    //console.log("MILES: " + miles)
    return miles


  }
解决方案

问题根源是service.nearbySearch是异步回调式API,外层for循环会一次性发起所有请求,而各个请求的回调完成顺序不固定,导致外层循环的输出无序。要解决这个问题,需要把异步回调API包装成Promise,然后用await让循环按顺序执行。

步骤1:修复distanceCalc的Promise封装

原代码中用Promise.resolve包装distanceService.route是错误的,因为route方法本身不返回Promise,需要手动封装:

async function distanceCalc(lat1, long1, lat2, long2){
    const pt1 = {lat: lat1, lng: long1}
    const pt2 = {lat: lat2, lng: long2}

    let distanceService = new google.maps.DirectionsService()
    // 手动封装route为Promise
    const dist = await new Promise((resolve, reject) => {
        distanceService.route({
            origin: pt1,
            destination: pt2, 
            travelMode: google.maps.TravelMode.DRIVING
        }, (result, status) => {
            if (status === google.maps.DirectionsStatus.OK) {
                resolve(result);
            } else {
                reject(new Error(`Distance calculation failed: ${status}`));
            }
        });
    });
    
    var miles = dist.routes[0].legs[0].distance.value
    miles = miles/1609.34
    return miles
}

步骤2:封装nearbySearch为Promise并按顺序执行循环

把nearbySearch包装成返回Promise的函数,在外层for循环中用await等待每个请求处理完成后再进入下一次循环:

async function getStations(pBounds){
    
    let gasMarkers = []
    var currTankSize = 0
    if (CurrentSize === "TFive"){
      currTankSize = TankSize*.25
      console.log("currTSIZE: " + currTankSize)
    } 
    else if(CurrentSize === "Fifty"){
      currTankSize = TankSize *.5
      console.log("currTSIZE: " + currTankSize)
    }
    else if(CurrentSize === "SFive"){
      currTankSize = TankSize*.75
      console.log("currTSIZE: " + currTankSize)
    }
    else{ currTankSize = TankSize
      console.log("currTSIZE: " + currTankSize)}
    distCoords.push([waypoints[0][0], waypoints[0][1]])
    var distTrack = 0
    
    const service = new google.maps.places.PlacesService(map)
    
    // 遍历循环改为顺序执行
    for (let i = 0; i < waypoints.length; i+=40){
      console.log("i before the second for loop: " + i)

      // 封装nearbySearch为Promise
      const results = await new Promise((resolve, reject) => {
          service.nearbySearch({
              location:{ lat: waypoints[i][0], lng:waypoints[i][1]},
              radius: '20000',
              type: ['gas_station']
          }, (results, status) => {
              if(status === google.maps.places.PlacesServiceStatus.OK){
                  resolve(results);
              } else {
                  reject(new Error(`Nearby search failed: ${status}`));
              }
          });
      });

      // 处理搜索结果
      for (var j = 0; j < results.length; j++){
        if(google.maps.geometry.poly.containsLocation(results[j].geometry.location,pBounds) === true){
          
          let dist = await distanceCalc(distCoords[distTrack][0], distCoords[distTrack][1], results[j].geometry.location.lat(), results[j].geometry.location.lng() )
          dist = dist / Mpg
          currTankSize = currTankSize - dist
          var gasLvl = currTankSize/TankSize
          console.log("i: " + i + " j: " + j+ " Gas: " + gasLvl)
          
          gasLvl = Math.round(gasLvl *10) / 10
          if (gasLvl <= .5){
            distCoords.push([results[j].geometry.location.lat(), results[j].geometry.location.lng()])
            distTrack+=1
            currTankSize = TankSize
            gasMarkers.push(new google.maps.Marker({
              position: results[j].geometry.location, map, 
              title: results[j]['name']
            }))

            let price;
            if(!setGas.has(results[j]['vicinity'])){
              price = await getGasStationInfo(results[j].geometry.location.lat(), results[j].geometry.location.lng())
            }

            var info = {
              name: results[j]['name'],
              vicinity: results[j]['vicinity'],
              price: price
            }
            if(!setGas.has(results[j]['vicinity'])){
              GasInformation.push(info);
              setGas.add(results[j]['vicinity'])
              console.log("INLOOP:" + GasInformation);
              GasSet = Array.from(new Set(GasInformation))
              setValueArray(GasSet)
            }
          }
        }
      }
    }
    setGasMarkerArray(gasMarkers)
}

关键说明

  • 把回调式API封装为Promise后,用await可以强制外层for循环等待当前请求的所有处理逻辑完成,再执行下一次循环,保证i的顺序输出。
  • 原代码中var price = getGasStationInfo(...)没有加await,会导致info.price是Promise对象,修改后添加await确保拿到实际价格值。
  • 移除了原有的searchPromises数组,因为现在不需要并行请求,而是顺序执行。

内容的提问来源于stack exchange,提问作者Mark

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 06:27:02