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

React Native Axios/Promise嵌套调用API的异步问题解决

问题场景

个人项目接入Yelp Fusion API时用到两类接口:

  • 一类可根据位置参数返回餐厅ID数组
  • 一类可根据餐厅ID返回对应餐厅的详情信息
    核心需求是先获取餐厅ID数组,再遍历ID拉取对应详情替换原数组中的条目,最终得到完整的餐厅详情数组,项目中使用Axios发起网络请求,原实现代码如下:
//Run the Business Search API to get 50 results, based on location and filters

function getRestaurantsFromYelp() {

  var axios = require('axios');

  var config = {
    method: 'get',
    url: `https://api.yelp.com/v3/businesses/search?limit=50&latitude=${lat}&longitude=${long}`,
    headers: { 
      'Authorization': 'Bearer [[authorization token]]'
    }
  };
  
  axios(config)
  .then(async function (response) {
    var restaurants = response.data.businesses      //array of 50 restaurants
    try {
      for (let i = 0; i < 3; i++) {
        let id = restaurants[i].id;
        let details = getRestaurantDetails(id);
        restaurants[i] = details;
      }
    } catch (error) {
      console.log(error)
    }
    setRestaurantData(((restaurants)));
  })
  .catch(function (error) {
    console.log(error);
  });


}

async function getRestaurantDetails(id) {
var axios = require('axios');

  var config = {
    method: 'get',
    url: `https://api.yelp.com/v3/businesses/${id}`,
    headers: { 
      'Authorization': 'Bearer [[authorization token]]'
    }
  };

  await axios(config)      
  .then(function (response) {
    return response.data;
  })
  .catch(function (error) {
    console.log(error);
  });

  return;
}

当前问题:details变量取值为undefined,餐厅详情接口返回时机晚于变量赋值时机。
备注:最终需要拉取全部50家商户的详情信息,当前调试阶段暂时将for循环设置为仅遍历前3个元素。

问题根因

代码里有两处核心的async/await逻辑错误:

  1. 调用getRestaurantDetails时没有加await关键字。该函数是async函数,默认返回Promise对象,不加await直接赋值的话,拿到的是未决议的Promise,不会等接口返回结果。
  2. getRestaurantDetails函数末尾写了空的return;,相当于主动返回undefined,就算axios请求成功拿到了response.data,也被这个空返回给覆盖了,函数根本不会把接口数据抛出去。
    另外还有个冗余问题:把require('axios')写在函数内部,每次调用函数都会重复执行模块加载逻辑,没有必要。
修复后可运行代码
// 顶部统一引入axios,不要在函数内重复require
const axios = require('axios');
// 统一复用请求头,减少重复代码
const YELP_REQUEST_HEADERS = {
  'Authorization': 'Bearer [[authorization token]]'
};

async function getRestaurantDetails(id) {
  try {
    const config = {
      method: 'get',
      url: `https://api.yelp.com/v3/businesses/${id}`,
      headers: YELP_REQUEST_HEADERS
    };
    const response = await axios(config);
    // 直接返回接口拿到的详情数据
    return response.data;
  } catch (error) {
    console.log(`获取ID为${id}的餐厅详情失败:`, error);
    // 请求失败返回null,做兜底避免整条数据为空
    return null;
  }
}

async function getRestaurantsFromYelp(lat, long) {
  try {
    const searchConfig = {
      method: 'get',
      url: `https://api.yelp.com/v3/businesses/search?limit=50&latitude=${lat}&longitude=${long}`,
      headers: YELP_REQUEST_HEADERS
    };
    const searchResponse = await axios(searchConfig);
    const restaurants = searchResponse.data.businesses;

    // 调试阶段先遍历前3个,逻辑跑通后把循环上限改成restaurants.length即可拉取全部50家
    for (let i = 0; i < 3; i++) {
      const restaurantId = restaurants[i].id;
      // 必须加await,等详情接口返回后再赋值
      const detailData = await getRestaurantDetails(restaurantId);
      if (detailData) {
        restaurants[i] = detailData;
      }
    }

    setRestaurantData(restaurants);
  } catch (error) {
    console.log('获取Yelp餐厅列表失败:', error);
  }
}
优化建议
  • 串行for循环请求50个接口速度较慢,调试通逻辑后可以换成Promise.all并发请求,速度会提升很多。如果触发Yelp API的限流规则,可以分批并发,比如一次发10个请求,一批完成后再发下一批。并发写法参考:
// 替换原来的for循环逻辑即可
const detailPromiseList = restaurants.map(item => getRestaurantDetails(item.id));
const fullRestaurantList = await Promise.all(detailPromiseList);
// 过滤掉请求失败返回null的项,也可以根据需求保留原简版数据
setRestaurantData(fullRestaurantList.filter(Boolean));
  • 不要把鉴权token硬编码在代码里,建议放到环境变量中存储,避免泄露。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 10:42:51