Цикл в отношении количества вызовов API и временного интервала

#vba #loops

#vba #циклы

Вопрос:

Я делаю кучу вызовов API на веб-сайт, который ограничивает количество вызовов API в час. Поскольку я иногда совершаю более 100 тыс. вызовов, иногда для получения всех необходимых мне данных требуются часы. Я хочу создать цикл, который проверяет, превышает ли количество вызовов API максимальное число в час, и если я превысил, проверьте разницу во времени между тем, когда я начал, и сейчас. Что-то вроде

 startTime = Now()

For i = 1 To 150000
    If counter <= 36000 Then
        url = baseURL   Str(i)   "?apikey="   apiKey
        resp.Open "GET", url
        resp.Send

        ' Process the response

        counter = counter   1
    Else # More than 36,000 API calls have been made
        Do
            # Nothing in the loop, just waiting for 60 minutes to pass
        While DateDiff(n, startTime, Now()) < 60

        startTime = Now()
        i = i - 1 # Need to re-loop on the current i
    End If
Next i
  

У меня еще не было возможности протестировать его, но на бумаге похоже, что это сработает, но также выглядит как халтура (особенно если i = i — 1). Есть ли лучший способ сделать то, что я пытаюсь сделать?

Ответ №1:

Обновление: как указал Коминтерн, я пропустил счетчик I.

Каждый раз, когда счетчик достигает отметки 36000, я бы проверил, прошел ли час. Если бы этого не произошло, я бы сбросил время начала и продолжил, иначе я бы запланировал повторный запуск макроса через 1 час после времени начала.

  Sub MakeAPICalls(Optional Counter As Long = 150000)

    Dim Start: Start = Timer
    Dim count As Long

    For I = Counter To 150000

        count = count   1

        URL = baseURL   Str(I)   "?apikey="   apiKey
        resp.Open "GET", URL
        resp.Send

        ' Process the response
        ' Exit Do if complete

        If (count Mod 36000) = 0 Then
            If (Timer - Start) < 3600 Then
                Start = Timer
            Else
                Application.OnTime Now   (3600 - (Timer - Start)), "MakeAPICalls " amp; I
                Exit Sub
            End If
        End If
    Next

End Sub
  

Комментарии:

1. Нравится OnTime вызов, но он не count должен быть статическим?

2. Счетчик и таймер могут быть сброшены, потому что вспомогательный модуль не будет вызываться снова, пока не истечет час. Часть, которая может потребоваться статической, — это код операционной системы. Я не могу сказать, когда он собрал все данные. Оператору придется структурировать свой код таким образом, чтобы многократное выполнение макроса все равно давало желаемый результат.

3. Имеет смысл. OP Str([loopcounter]) встроен в URL. Я просто подумал, что было бы проще повторно count использовать .

4. @Comintern Спасибо. Как я это пропустил!! Пожалуйста, ознакомьтесь с моим обновленным ответом.

5. Что заняло так много времени? Вы получили мой 1 почти час назад !! .. ЛОЛ, я просто хотел убедиться, что я ничего не пропустил.

Ответ №2:

Я бы упростил это, используя 2 вложенных цикла. Выполните внешний цикл по вашему количеству запросов, затем используйте внутренний цикл для выполнения ваших 36 тыс. запросов:

 Dim requests As Long
For i = 1 To 150000 Step 36000
    If i > 144000 Then requests = 5999 Else requests = 35999
    For x = 0 To requests
        URL = baseURL   Str(i   x)   "?apikey="   apiKey
        resp.Open "GET", URL
        resp.Send
        ' Process the response
    Next
    Sleep 3600000 '1 hour
Next
  

Обратите внимание, что при этом используется Sleep вызов API:

 Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
  

Это гарантирует, что ваш процессор не будет загружен на 100% в течение часа в цикле бездействия. Если вы хотите, чтобы Excel оставался отзывчивым ( Sleep буквально приостанавливает поток, в котором он выполняется), вы можете поместить a DoEvents в свой цикл NOP, но это все равно будет потрачено впустую. тонны циклов процессора.

Комментарии:

1. Хорошо, я пропустил чтение вашего последнего утверждения. Я думаю, это Sleep 1000:DoEvents был бы хороший компромисс. Sleep 3600000 вероятно, следует скорректировать с учетом времени, необходимого для получения 36 тыс. вызовов (если для обработки 36 тыс. вызовов требуется 59 минут, макрос должен приостановиться на 1 минуту).