¿Por qué se bloquea esta función de obtención de datos de VBA?

¿Por qué se bloquea esta función de obtención de datos de VBA?

Escribí esta función en VBA para recuperar datos de una URL. Lo estoy llamando desde otra función que se llama en una consulta de Access. El código está adaptado del código de un artículo citado en los comentarios del código:

'========================================================
Public Function sURLfetch(ByVal sURL As String) As String
'========================================================
' Return data found at a URL.

' From "www.MyExcelGenius.com/getting-data-from-a-website-in-json-format-using-vba/".
' Requires reference "Microsoft XML, v6.0".

Const bRunAsynch As Boolean = True
Const nProcessComplete As Integer = 4

Dim oRequest As MSXML2.XMLHTTP60
Set oRequest = New MSXML2.XMLHTTP60

Dim sResponse As String

With oRequest
    .Open "get", sURL, bRunAsynch
    .setRequestHeader "Content-Type", "application/json"
    .send

    Do While oRequest.ReadyState <> nProcessComplete
        DoEvents
      Loop
    
    sResponse = .responseText
  End With

sURLfetch = sResponse

'========================================================
End Function        ' sURLfetch()
'========================================================

Cuando se llama a esta función, se bloquea VBA. Pero aquí está lo extraño: si establezco un punto de interrupción en la línea:

Do While oRequest.ReadyState <> nProcessComplete

y luego decirle a VBA que continúe desde allí, luego funciona bien y devuelve el resultado deseado. Hace esto una y otra vez, devolviendo la secuencia adecuada de resultados, siempre que el código se interrumpa en ese punto de interrupción y luego continúe. Sin embargo, si elimino ese punto de interrupción y establezco un punto de interrupción en la línea justo después del bucle:

sResponse = .responseText

luego se cuelga y no obtengo nada.

Entonces, por alguna razón, esta función se bloquea en el ciclo a menos que un punto de interrupción le indique que haga una pausa antes de ingresar al ciclo.

El propósito del bucle es garantizar que el proceso de búsqueda se haya completado antes de registrar la respuesta. He observado el funcionamiento del código y el ciclo generalmente se repite cero o una vez. Cuando se repite, significa que la búsqueda estaba incompleta y era necesario finalizarla. Entonces el bucle es necesario para lo que estoy buscando. Y por alguna razón, parece funcionar bien siempre que haya un punto de interrupción antes, pero por lo demás se bloquea misteriosamente.

La DoEventsfunción, todo el contenido del bucle, simplemente le dice a VBA que permita que el sistema operativo haga lo que sea que esté sucediendo mientras se ejecuta el bucle. Esa llamada a función está en elcódigo originaladaptado aquí y hay documentación de la función pormicrosoftypozo.

Intenté automatizar la pausa insertando una llamada a una función que pausa VBA por un tiempo aleatorio. Eso no impidió que la función se colgara.

Resumen:

  • La función funciona si está pausada por un punto de interrupción al comienzo del ciclo.
  • Se cuelga si se llama sin un punto de interrupción o con un punto de interrupción después de ese bucle.

¿Qué podría estar causando que esta función se cuelgue y qué podría cambiar para que funcione?

Respuesta1

Parece que el problema fue configurar el asynchparámetro en el Opencomando en True. ese escenariopermite que la solicitud se detenga antes de que finalice, que es lo que hizo DoEventsnecesario el bucle. Así que intenté cambiar ese parámetro Falsey comentar el bucle. Después de eso, la función parece funcionar bien.

No sé por qué elcódigo originalusado asynch= Truey el bucle. Eso parece haber sido lo que hizo que la función no funcionara.

información relacionada