循环等待 API 响应

Posted

技术标签:

【中文标题】循环等待 API 响应【英文标题】:Await for API response in a loop 【发布时间】:2017-07-21 07:09:33 【问题描述】:

我正在遍历一个数组并为每个项目进行 REST API 调用,但我遇到了 js 的异步性质的问题。我正在尝试使用 async/await,但我认为我没有正确设置它,因为它不会等待响应并返回 undefined。

onSearchSuccess = async (response) => 
  const persons = response._embedded.persons_search_collection;
  const personsWithClasses = await persons.reduce(
  (acc, person) => 
    const params = 
      person_id: person.person_id,
      date: '2017-01-05',
      enrollment_status: 3,
      class_status: 2,
    ;
    return getClasses( //this function does an GET request and returns the response
      params,
      (classesResponse) => 
        const  classes  = classesResponse._embedded;
        console.log(classes); //logs after the console.log below
        return [...acc,  ...person, classes ];
      ,
      () => acc,
    );
  , []);
console.log(personsWithClasses); //return undefined



export const getClasses = (params, success, error) => 
  axios.get(`$uri/classes`,  params )
  .then(( data ) => 
    success(data);
  )
  .catch(err => error(err));
;

【问题讨论】:

如果getClasses classes 返回一个promise,那么你不能做[...acc] 因为acc 将是一个promise。你为什么在这里使用reduce?您究竟想达到什么目的?您想按顺序执行所有 REST 吗?还是干脆等到所有请求都完成? 基本上我有一群人,我正在请求获取每个人的课程,如果那天有那个人的课程,那么返回一个包含人和人的对象类,否则只需返回累加器并继续。我基本上想过滤掉没有类的人,如果有的话,返回一个带有人的属性和类的新对象。 如果我提供getClasses的代码会有帮助吗? reduce 是同步的。使用异步函数(getClasses 是什么)作为reduce 回调没有意义。请改用.mapPromise.all 好的,谢谢,我会重写它以使用promise.all 【参考方案1】:

正如我在 cmets 中提到的,如果您调用异步函数,reduce 将无法正常工作。你可以像这样使用Promise.all.map(我尽量使用async/await):

onSearchSuccess = async (response) => 
  const persons = response._embedded.persons_search_collection;
  let personsWithClasses = await Promise.all(persons.map(async (person) => 
    try 
      const classes = await getClasses(
        person_id: person.person_id,
        date: '2017-01-05',
        enrollment_status: 3,
        class_status: 2,
      );

      return ...person, classes;
     catch(error) 
      // ignore errors if a person wasn't found
      return null;
    
  ));
  personsWithClasses = personsWithClasses.filter(x => x != null);
  console.log(personsWithClasses);



export const getClasses = params => 
  return axios.get(`$uri/classes`,  params );
;

还要注意我对getClasses 所做的更改。如果axios.get 无论如何返回一个promise,就没有理由让它接受回调。

【讨论】:

谢谢!我忘了用 promise.all 更新我正在使用的所有代码,但我已经接近了。只是没有 try/catch 部分。 我真的很想让这个模型工作,我尝试了很多其他的东西,但都失败了......一个问题,这部分return ...person, classes;我的版本不接受classes 来自在它上面的行中创建的变量。为什么会这样?这是我的版本:let id = response.faceId return ...imageName, id 创建它的id是灰色的,它不会让return语句中的id使用它。

以上是关于循环等待 API 响应的主要内容,如果未能解决你的问题,请参考以下文章

等待函数完成,直到回调到来

sh 等待来自URL的200响应循环

如何使用 Alamofire 等待 API 响应 [重复]

Javascript等待Promise在返回响应之前完成for循环

等待 api 中的空响应

Swift:如何对服务进行 API 调用但不等待响应