我使用Visual Basic和Excel从API获取一些数据。我在For-Each循环的每次迭代中运行大约100个API调用,每次迭代将填充一行数据。
问题是,我的excel在完成大约4-5行后冻结了!
我认为这个问题的最佳解决方案是在每次API调用之间有大约3秒的延迟。这也可以防止我的API出现速率限制错误。
这是我目前的代码 -
For Each BidRow In Range("A2:A102")
MyRequest.Open "GET", "https://api.someapi.com/values/" & Range("B" & RowNo)
MyRequest.Send
Set JsonBid = JsonConverter.ParseJson(MyRequest.ResponseText)
Range("D" & RowNo).Value = JsonBid("key")
RowNo = RowNo + 1
Next BidRow
JsonConverter只是另一个模块。
无论如何,我不知道在Visual Basic中做任何延迟3000毫秒的方法,在使用settimeout()函数的Javascript中很容易做到这一点。或者我可能需要一些异步编码技术。我现在迷失了很多东西!
不知道怎么解决这个问题?
您可以使用此子项暂停指定数量的“整个”秒:
Sub Pause(delaySeconds As Integer)
Dim startTime As Single
startTime = Timer
Do While Timer < startTime + delaySeconds
DoEvents ' Yield to other processes
Loop
End Sub
例如,Pause(3)
将暂停3秒钟。
但是,您确定Excel以不可恢复的方式“冻结”吗?我使用了很多API,我知道当我循环几百次时,看起来确实看起来像是崩溃了,但是有点耐心,这个过程确实完成了。
如果你在100 × 3 seconds = 5 minutes
之前添加了一行,而不是暂停(并通过Next BidRow
延长你的sub的执行时间):
DoEvents
编辑重新:每秒60次调用的API限制...
如果提供API的网站每分钟限制为60次,那么您的100次通话应该在不少于100秒的时间内运行。我打赌你低于那个但你可以通过计时程序来确保。
循环之前,您可以添加:
Dim LoopStart as Single
LoopStart = Timer
...然后在循环完成后,添加一行:
MsgBox "Loop finished in " & Round(Timer - LoopStart,0) & " seconds."
如果超出限制,大多数API只会返回一个错误,并在一两秒内正常恢复。我确信有一些例外,取决于您使用的API的精细打印,理论上该网站可能会从您的信用卡收取过多的电话(需要事先商定)或可能禁止你的知识产权经过多次滥用(我从未见过)。
例如,Google Maps Geocoding API有一个非常慷慨的“标准”限制:
每天2,500免费请求,以及
每秒50个请求。
默认情况下,超过此值的调用将返回(临时)错误,除非您使Enable Billing解锁更高的配额:
每天2,500个免费请求,然后,您需要支付0.50美元/ 1000个额外请求,每天最多100,000个
(Qazxswpoi)
您可以确保循环的每次迭代至少需要一秒钟,如下所示:
Source