Posteriormente a consultar expertos en esta materia, programadores de varias áreas y maestros hemos dado con la respuesta a la cuestión y la plasmamos en esta publicación.
FileReader.readAsDataURL()
es asincrónico – la descarga ocurre en segundo plano mientras el resto del código sigue ejecutándose. Entonces la razón console.log(my_pdf_file_as_base64);
imprime un vacío string es esa la linea my_pdf_file_as_base64 = e.target.result
aún no se ha ejecutado: la llamada a getBase64()
finaliza casi inmediatamente y se ejecuta la instrucción posterior; solo más tarde (cuando se complete la descarga) se ejecutará la devolución de llamada.
La forma de manejar esto es colocar el código que usa el archivo descargado dentro la devolución de llamada:
getBase64(my_pdf_file, function(e)
my_pdf_file_as_base64 = e.target.result;
console.log(my_pdf_file_as_base64);
);
Alternativamente, puede repetidamente (por ejemplo, dentro de un setTimeout
devolución de llamada o dentro de algún controlador de eventos DOM) compruebe si reader.readyState === FileReader.DONE
– cada vez que esto se convierte true, reader.result
contendrá el archivo.
Un enfoque más flexible es utilizar un Promise
, que es un objeto que encapsula un cálculo asíncrono:
function getBase64(file, onLoadCallback)
return new Promise(function(resolve, reject)
var reader = new FileReader();
reader.onload = function() resolve(reader.result); ;
reader.onerror = reject;
reader.readAsDataURL(file);
);
var promise = getBase64(my_pdf_file);
promise.then(function(result)
console.log(result);
);
Hasta ahora, esto parece bastante similar a la primera solución, pero la ventaja es que promise
es un objeto que puede pasar a otras funciones, de modo que puede iniciar un cálculo en un lugar y decidir en otro lugar qué debe suceder cuando finaliza.
Como probablemente haya notado, ninguno de estos enfoques le permite bloquear la ejecución de código adicional hasta que el contenido del archivo se haya asignado a la variable global. my_pdf_file_as_base64
. Esto es por diseño; sin embargo, si realmente necesita bloquear la descarga porque no tiene tiempo para refactorizar el código antiguo, consulte la discusión en https://stackoverflow.com/a/39914235/626853. Si los navegadores de su usuario son lo suficientemente modernos, puede usar async/await:
$(document).on("click", ".clicker", async function()
var promise = getBase64(my_pdf_file);
var my_pdf_file_as_base64 = await promise;
(Tenga en cuenta que await
solo funciona por dentro async
funciones, por lo que su controlador de clic debe ser async
. También experimenté agregando un bucle de espera ocupado, pero eso hizo que mi navegador se bloqueara).
Te mostramos comentarios y calificaciones
Eres capaz de añadir valor a nuestro contenido informacional asistiendo con tu veteranía en las interpretaciones.