Есть ли способ замедлить асинхронные вызовы выборки внутри цикла for / forEach, чтобы избежать квот на API в секунду? - PullRequest
0 голосов
/ 06 февраля 2019

Я работаю над приложением, для которого требуются вызовы в API Foursquare Places с квотой 2 вызова в секунду.Приложение тянет список мест, а затем должен отдельно вызывать фотографии для каждого места.Я попытался сделать это внутри функции forEach и внутри функции For-In.Я перепробовал все, что мог придумать, и нашел исследование, чтобы выполнить эту работу (от использования setTimeout в различных ситуациях до создания обещаний с включенными тайм-аутами и их включением во многих различных способах), но я не смог найти никаких решенийчтобы помочь в моей конкретной ситуации асинхронного / ожидания получения.

Чтобы было ясно - приложение работает, и мое заявление "else" включается, но выражение else срабатывает, потому что я превышаю квоту в секунду - так, код есть, иработая, я просто хочу иметь возможность запускать фотографии вместо обычных иконок.Я могу заставить фотографии работать, если я буду ждать достаточно долго, как будто сервер на секунду забывает.Но мои общие ежедневные квоты намного превышают все, что я когда-либо мог достичь в среде разработчиков, поэтому это должно быть то, что доставляет мне неприятности!

Если кто-то может помочь, я был бы очень признателен!

const renderVenues = (venues) => {
  for(let i=0; i < $venueDivs.length; i++){
    const $venue = $venueDivs[i];
    const venue = venues[i];
    let newUrl = `https://api.foursquare.com/v2/venues/${venue.id}/photos?client_id=${clientId}&client_secret=${clientSecret}&v=20190202`;
    const getPics = async () =>{
      try{
      const picResp = await fetch(newUrl);
      if(picResp.ok){
        const picJson = await picResp.json();
        const photo = picJson.response.photos.items[0];
        const venueImgSrc = `${photo.prefix}300x300${photo.suffix}`;
        let venueContent = `<h2>${venue.name}</h2><h4 style='padding-		top:15px'>${venue.categories[0].name}</h4>
        <img class="venueimage" src="${venueImgSrc}"/>
        <h3 style='padding-top:5px'>Address:</h3>
        <p>${venue.location.address}</p>
        <p>${venue.location.city}, ${venue.location.state}</p>
        <p>${venue.location.country}</p>`;
        $venue.append(venueContent);
      } else{
          const venueIcon = venue.categories[0].icon;
          const venueImgSrc = `${venueIcon.prefix}bg_64${venueIcon.suffix}`;
          let venueContent = `<h2>${venue.name}</h2><h4 style='padding-top:15px'>${venue.categories[0].name}</h4>
    <img class="venueimage" src="${venueImgSrc}"/>
    <h3 style='padding-top:5px'>Address:</h3>
    <p>${venue.location.address}</p>
    <p>${venue.location.city}, ${venue.location.state}</p>
    <p>${venue.location.country}</p>`;
      $venue.append(venueContent);
      }
    }
    catch(error){
        console.log(error)
        alert(error)
      }
    }
    getPics();
  }

  $destination.append(`<h2>${venues[0].location.city}, ${venues[0].location.state}</h2>`);
}

//and then below, I execute the promise(s) that this is included with.

getVenues().then(venues =>
    renderVenues(venues)
  )

Ответы [ 2 ]

0 голосов
/ 06 февраля 2019

Если вы обнаружите, что в вашем приложении происходит такое же регулирование, модуль https://github.com/SGrondin/bottleneck предоставляет удобный интерфейс для их выражения.

0 голосов
/ 06 февраля 2019

На каждой итерации вы можете await a Promise, который разрешается через 0,6 секунды:

const delay = ms => new Promise(resolve => setTimeout(resolve, ms));
const renderVenues = async (venues) => {
  for(let i=0; i < $venueDivs.length; i++){
    // ...
    await getPics();
    // no need for a trailing delay after all requests are complete:
    if (i !== $venueDivs.length - 1) {
      await delay(600);
    }
  }
  $destination.append(...)
};
...