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

Next.js Google Places API报错:API未返回响应求助

问题

我用Google Maps编写了获取指定坐标附近场所及海滩的代码,在Next.js组件中通过useSWR钩子调用该API接口。所有数据均可正常返回,但在首次执行Axios调用前,控制台出现错误提示:

API resolved without sending a response for /api/google/places/33.807501/-78.70039, this may result in stalled requests.

作为新手无法定位问题所在,希望得到解决建议,相关代码如下:

const axios = require("axios");
const GetNearbyPlaces = async (req, res) => {
  const { latitude, longitude } = req.query;

  const radius = 50000;

  const types = [
    "airport",
    "tourist_attraction",
    "amusement_park",
    "aquarium",
    "art_gallery",
    "bar",
    "museum",
    "night_club",
    "cafe",
    "restaurant",
    "shopping_mall",
    "store",
    "spa",
  ];

  function checkFunc(arr, val) {
    return arr.some(arrVal => val === arrVal);
  }

  const url = `https://maps.googleapis.com/maps/api/place/nearbysearch/json?location=${latitude}%2C${longitude}&radius=${radius}&key=${process.env.CW_GOOGLE_MAPS_API_KEY}`;

  const beachesUrl = `https://maps.googleapis.com/maps/api/place/nearbysearch/json?location=${latitude}%2C${longitude}&radius=${radius}&type=natural_feature&key=${process.env.CW_GOOGLE_MAPS_API_KEY}`;

  try {
    let results = [];
    let beaches = [];
    const fetchNearbyBeaches = async (urlWithToken = null) => {
      await axios.get(urlWithToken ? urlWithToken : beachesUrl).then(data => {
        beaches = [...beaches, ...data.data.results];
        if (data?.data?.next_page_token) {
          const newUrl = `https://maps.googleapis.com/maps/api/place/nearbysearch/json?key=${process.env.CW_GOOGLE_MAPS_API_KEY}&pagetoken=${data.data.next_page_token}`;

          setTimeout(() => {
            fetchNearbyBeaches(newUrl);
          }, 2000);
        } else {
          beaches.length > 5 && beaches.splice(5);
          results.length > 5 && results.splice(5);

          const finalResults = [...beaches, ...results];

          finalResults.length > 10 && finalResults.splice(10);
          return res.status(200).json({
            data: { results: finalResults },
            success: true,
          });
        }
      });
    };

    const fetchNearbyPlaces = async (urlWithToken = null) => {
      await axios.get(urlWithToken ? urlWithToken : url).then(data => {
        results = [...results, ...data.data.results];
        if (data?.data?.next_page_token) {
          const newUrl = `https://maps.googleapis.com/maps/api/place/nearbysearch/json?key=${process.env.CW_GOOGLE_MAPS_API_KEY}&pagetoken=${data.data.next_page_token}`;

          setTimeout(() => {
            fetchNearbyPlaces(newUrl);
          }, 2000);
        } else {
          const dirtyResultsWithDuplicates = [];
          results.map(result => {
            return types.map(type => {
              if (checkFunc(result.types, type) && !result.types.includes("lodging")) {
                dirtyResultsWithDuplicates.push(result);
              }
            });
          });

          const set = new Set(dirtyResultsWithDuplicates);
          const filtered = Array.from(set);

          results = filtered.length > 10 ? filtered.splice(10) : filtered;
          
          return fetchNearbyBeaches();
        }
      });
    };

    fetchNearbyPlaces();
  } catch (err) {
    res.status(500).json({
      message: err.message,
      statusCode: 500,
    });
  }
};

export default GetNearbyPlaces;
解决建议

问题根源

  1. API路由函数GetNearbyPlaces是异步函数,但调用fetchNearbyPlaces()时未加await,导致Next.js误以为路由逻辑已执行完毕,提前结束请求上下文,而实际异步请求还在处理,因此抛出警告。
  2. 使用setTimeout嵌套调用异步函数时,没有正确处理Promise链,导致后续响应逻辑脱离当前请求上下文,进一步加剧问题。

修复步骤

  1. 添加await等待异步函数执行:调用fetchNearbyPlaces()时加上await,确保Next.js等待所有异步操作完成后再结束路由。
  2. 替换setTimeout为Promise延迟函数:把setTimeout改成返回Promise的函数,用await等待延迟后再请求下一页,保证Promise链完整性。
  3. 统一使用async/await替代.then():简化代码逻辑,避免回调嵌套导致的上下文丢失。

修改后的代码示例

const axios = require("axios");

// 封装延迟函数,替代setTimeout
const delay = (ms) => new Promise(resolve => setTimeout(resolve, ms));

const GetNearbyPlaces = async (req, res) => {
  const { latitude, longitude } = req.query;

  const radius = 50000;

  const types = [
    "airport",
    "tourist_attraction",
    "amusement_park",
    "aquarium",
    "art_gallery",
    "bar",
    "museum",
    "night_club",
    "cafe",
    "restaurant",
    "shopping_mall",
    "store",
    "spa",
  ];

  const checkFunc = (arr, val) => arr.some(arrVal => val === arrVal);

  const url = `https://maps.googleapis.com/maps/api/place/nearbysearch/json?location=${latitude}%2C${longitude}&radius=${radius}&key=${process.env.CW_GOOGLE_MAPS_API_KEY}`;

  const beachesUrl = `https://maps.googleapis.com/maps/api/place/nearbysearch/json?location=${latitude}%2C${longitude}&radius=${radius}&type=natural_feature&key=${process.env.CW_GOOGLE_MAPS_API_KEY}`;

  try {
    let results = [];
    let beaches = [];

    const fetchNearbyBeaches = async (urlWithToken = null) => {
      // 用await替代.then()
      const data = await axios.get(urlWithToken ? urlWithToken : beachesUrl);
      beaches = [...beaches, ...data.data.results];
      
      if (data?.data?.next_page_token) {
        const newUrl = `https://maps.googleapis.com/maps/api/place/nearbysearch/json?key=${process.env.CW_GOOGLE_MAPS_API_KEY}&pagetoken=${data.data.next_page_token}`;
        // 用await等待延迟后再递归调用
        await delay(2000);
        await fetchNearbyBeaches(newUrl);
      } else {
        // 截取数据
        if (beaches.length > 5) beaches.splice(5);
        if (results.length > 5) results.splice(5);
        
        const finalResults = [...beaches, ...results];
        if (finalResults.length > 10) finalResults.splice(10);
        
        res.status(200).json({
          data: { results: finalResults },
          success: true,
        });
      }
    };

    const fetchNearbyPlaces = async (urlWithToken = null) => {
      // 用await替代.then()
      const data = await axios.get(urlWithToken ? urlWithToken : url);
      results = [...results, ...data.data.results];
      
      if (data?.data?.next_page_token) {
        const newUrl = `https://maps.googleapis.com/maps/api/place/nearbysearch/json?key=${process.env.CW_GOOGLE_MAPS_API_KEY}&pagetoken=${data.data.next_page_token}`;
        // 用await等待延迟后递归
        await delay(2000);
        await fetchNearbyPlaces(newUrl);
      } else {
        // 过滤数据
        const dirtyResultsWithDuplicates = [];
        results.forEach(result => {
          types.forEach(type => {
            if (checkFunc(result.types, type) && !result.types.includes("lodging")) {
              dirtyResultsWithDuplicates.push(result);
            }
          });
        });
        
        const filtered = Array.from(new Set(dirtyResultsWithDuplicates));
        results = filtered.length > 10 ? filtered.slice(0, 10) : filtered;
        
        // 等待海滩数据获取完成
        await fetchNearbyBeaches();
      }
    };

    // 等待所有异步操作完成
    await fetchNearbyPlaces();
  } catch (err) {
    res.status(500).json({
      message: err.message,
      statusCode: 500,
    });
  }
};

export default GetNearbyPlaces;

内容的提问来源于stack exchange,提问作者Agustin G.

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 20:35:26