ruandeses
Queridos todos,
Estoy tratando de realizar una solicitud GET después de una solicitud POST.
La solicitud POST devuelve una ID que se necesita para la solicitud GET.
La solicitud POST funciona y devuelve la ID necesaria.
Al realizar la solicitud GET, aparece el problema «Llegamos al final del búfer» que creo que se está generando porque el archivo aún no está listo.
Al crear una nueva consulta y realizar la solicitud POST y GET por separado, agregando manualmente la ID en la solicitud GET: la actualización falla la primera vez.
Si luego trato de actualizar la página por segunda vez, la solicitud GET es exitosa.
Pensé que la solicitud GET desencadena una descarga que se puede recuperar una vez completada, así que intenté realizar un InvokeAfter basado en el blog de @cwebb, que no tuvo éxito. Agregué una duración de 10 segundos que también devuelve el error en el primer intento y devuelve un conjunto de datos exitoso en la segunda actualización.
Al explorar la actualización fallida y abrir el archivo como texto, el archivo está vacío después de la primera actualización y contiene el formato JSON después de la segunda actualización.
¿Alguien sabe cómo resolver este problema?
Vea el siguiente código:
dejar
//POST solicitud
base_url = «https://*****/api/dataviewresult/»&Dataview&»/json?»,
extensión = «clave_api=*****»,
url = base_url & extensión,
encabezado = [#»Content-Type» = «application/json»],
contenido1= «{}»,
webdata1 = Web.Contents(url, [Headers=header,Content = Text.ToBinary(content1)]),
respuesta1 = Json.Document(webdata1),
contenido = respuesta1[contents],
id = contenido[id],
// OBTENER solicitud
get_data = Json.Document(Web.Contents(«https://*****/api/dataviewresult/» & Dataview & «/json/» & id & «?api_key=*****»)),
en
obtener datos
lo que intenté hacer para invocar la solicitud GET después de 10 segundos (el siguiente código es en lugar de la parte get_data):
dejar
Fuente = ()=> Json.Document(Web.Contents(«https://*****/api/dataviewresult/***dataview-ID***/json/***ID****? clave_api=*****»)),
Demora = prueba Function.InvokeAfter(Source, #duration(0,0,0,10)) de lo contrario 0,
(todas las partes con *** han sido eliminadas)
lbendlin
Sí, esa pausa de «Evaluación» es exasperante. Mi solución hasta ahora es dejar que siga su curso, ir a tomar un café, leer un buen libro, etc. Afortunadamente, esta renovación de metadatos solo se retrasa una vez, bueno, hasta la próxima vez que haga cambios drásticos. 🙂
ruandeses
En respuesta a lbendlin
Hmm, la consulta se ejecutó durante aproximadamente 6 horas sin ningún resultado. ¿Es posible arreglar esto o es una causa perdida?
ruandeses
@lbendlin Cambié mi consulta que resuelve el problema del caché al hacer un bucle con una función, pero ahora me quedo atascado en la parte «evaluar». Mi consulta se carga perfectamente en el editor de consultas, pero cuando cierro y aplico mi consulta se atasca en la parte «Evaluando». Cambiar los niveles de privacidad, ignorar los niveles de privacidad y deshabilitar «Permitir que las vistas previas de datos se descarguen en segundo plano» no funcionan. ¿Alguna idea sobre lo que puedo hacer para solucionar esto?
Consulta:
dejar
//Generar el ID necesario para la función
id = Json.Documento(Web.Contents(«https://*****/api/dataviewresult/»&Dataview&»/json?api_key=*****», [Headers=[#»Content-Type» = «application/json»],Contenido = Texto.ToBinary(«{}»)]))[contents][id],
//Función de estado de llamada que devuelve la URL de solicitud GET una vez que tiene éxito
Fuente = Status_dataview (Dataview, id),
//Crear función para obtener los datos basados en la función anterior
DownloadFile1 = () => Json.Document(Web.Contents(Source&»?api_key=*****»)),
//Llamar a la función que comienza después de 10 segundos
DownloadFile = Function.InvokeAfter(DownloadFile1, #duration(0,0,0,10)),
//Preparación de datos
#»Convertido a tabla» = *****
#»Columna Expandida1″ = *****
en
#»Columna Expandida1″
Función (Status_dataview):
(vista de datos como texto, id como texto) =>
dejar
//Función para obtener la URL una vez que tenga éxito en función de los campos/parámetros: Dataview, id
Datos = () => Json.Document(Web.Contents(«https://*****/api/dataviewresult/» & Dataview & «/json/» & id & «/status?api_key=*** **»))[contents][status],
//Llamar a la función después de 10 segundos
Invocar = Función.InvocarDespués(Datos,#duración(0,0,0,10)),
// Repita la función cada 10 segundos, hasta que el estado sea exitoso
salida =
si Invocar = «éxito», entonces Json.Document(Web.Contents(«https://*****/api/dataviewresult/» & Dataview & «/json/» & id & «/status?api_key=** ***»))[contents][url] else @Status_dataview(Dataview, id)
en
producción
lbendlin
sí, pero no puede proporcionar «r = 1» a cada GET, eso anula el propósito. Tiene que ser un número diferente para cada llamada.
ruandeses
En respuesta a lbendlin
Intenté agregar un Índice y luego hacer referencia al índice, como: r=Text.From([Index]). Esto arroja un error 404.
Consulte la documentación de la API adjunta, que puede ser útil: manual.yesplan.be/nl/developers/dataviews. También probé el blog de Chris Webbs: web-contents-caching-and-the-excludedfromcachekey-option-in-power-bi-and-power-query agregando un encabezado, pero creo que no puedo agregar encabezados/consultas a este GET solicitud.
¿Alguna idea sobre cómo abordar el problema del almacenamiento en caché? También puedo enviar el archivo personalmente si eso ayuda.
lbendlin
Es posible que esté sufriendo un caso grave de almacenamiento en caché. Agregue un parámetro aleatorio a cada una de sus solicitudes GET.
…&r=
ruandeses
En respuesta a lbendlin
¿Quieres decir así? (simplemente agregando &r=1 por ejemplo) ¿Debería agregarlo solo al GET para el estado? Como este es el valor que necesito («éxito») para que la consulta pase a la fase de «descarga».
// OBTENER el estado 10x después de 5 segundos
#»Personalizado añadido» = Table.AddColumn(#»Convertido a tabla», «Personalizado», cada Función.InvokeAfter(
() => Json.Document(Web.Contents(«https://*****/api/dataviewresult/» & Dataview & «/json/» & id & «/status?api_key=***** «&r=1))[contents][status],
#duración(0,0,0,[Column1]))),
lbendlin
Si está seguro de que el segundo GET funcionará, puede llamar al GET dos veces y usar el resultado de la segunda llamada.
Por supuesto, sería bueno entender por qué falla exactamente el primer GET.
ruandeses
En respuesta a lbendlin
Gracias por su respuesta, ahora entiendo por qué falla el primer GET.
El motivo es que mi primera solicitud POST desencadena la creación del archivo.
Una vez que se genera el archivo, puedo realizar la solicitud GET para recuperar el archivo.
Por eso en el segundo intento, 9 de cada 10 veces consigo el archivo.
Lo que intenté es crear una función InvokeAfter con un ciclo de 10 x 5 segundos (50 segundos en total) y devolver el estado (esta es una solicitud GET separada que leí ayer en la documentación de la API). Una vez que una de las filas devuelve «éxito», la consulta debe continuar con la solicitud GET original para recuperar el archivo.
Desafortunadamente, sigo obteniendo el estado «en ejecución», sin importar si digo ejecutarlo 10 veces durante 5 segundos o 10 veces durante 1 segundo. Pero cuando pruebo el enlace en mi navegador, el estado ya es «éxito». Parece que algo anda mal con la función InvokeAfter. Mi intención es que después de realizar la solicitud POST, el estado se recupere después de 5 – 10 – 15 hasta 50 segundos. Una vez que uno de estos resultados sea «éxito», puedo proceder a descargar el archivo.
Ver código:
dejar
//POST solicitud
base_url = «https://*****.nl/api/dataviewresult/»&Dataview&»/json?»,
extensión = «clave_api=*****»,
url = base_url & extensión,
encabezado = [#»Content-Type» = «application/json»],
contenido1= «{}»,
webdata1 = Web.Contents(url, [Headers=header,Content = Text.ToBinary(content1)]),
respuesta1 = Json.Document(webdata1),
contenido = respuesta1[contents],
id = contenido[id],
// ESPERA tabla
EsperarLista = Lista.Repetir({5}, 10),
#»Convertido a tabla» = Table.FromList(WaitForList, Splitter.SplitByNothing(), null, null, ExtraValues.Error),
// OBTENER el estado 10x después de 5 segundos
#»Personalizado añadido» = Table.AddColumn(#»Convertido a tabla», «Personalizado», cada función.InvokeAfter(
() => Json.Document(Web.Contents(«https://*****/api/dataviewresult/» & Dataview & «/json/» & id & «/status?api_key=***** «))[contents][status],
#duración(0,0,0,[Column1]))),
// Agregue GET URL para verificar si la ID / Dataview ID es correcta
#»Personalizado2 agregado» = Table.AddColumn(#»Personalizado agregado», «Personalizado2», cada Json.Document(Web.Contents(«https://*****/api/dataviewresult/» & Dataview & «/ json/» & id & «/estado?api_key=*****»))[contents][url]),
#»Tipo cambiado» = Table.TransformColumnTypes(#»Personalizado2 agregado»,{{«Personalizado», escriba texto}}),
// esperar hasta que la respuesta esté COMPLETA, pero máximo 50 segundos
WaitForStatus = Table.MatchesAnyRows(#»Tipo cambiado», cada uno [Custom] = «éxito»),
// descarga el archivo si WaitForStatus fue exitoso
Descargar archivo =
si WaitForStatus entonces
Json.Documento(Web.Contents(«https://*****/api/dataviewresult/» & Dataview & «/json/» & id & «?api_key=*****»))
demás
nulo
en
Descargar archivo