Quiero obtener una cadena base64 de una imagen cargada. La primera vez que ejecuto el código, devuelve indefinido. Cuando corro después funciona bien. ¿Cómo puedo arreglar esto?
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Upload</title> </head> <body> <input type="file" id="file"> <button id="button" onclick="upload()">Upload</button> <script type="text/javascript"> var result; function getBase64(file) { var reader = new FileReader(); reader.readAsDataURL(file); reader.onload = function () { result = reader.result; }; reader.onerror = function (error) { console.log('Error: ', error); }; return result; } function upload() { var file = document.querySelector('input').files[0]; console.log(getBase64(file)); } </script> </body> </html>necesita declarar FileReader fuera de upload() y usar la función onload para console.log .
var reader = new FileReader(); reader.onload = function (event) { var dataURL = event.target.result; console.log(dataURL); }; en la función de update use solo readDataURL
function upload() { var file = document.querySelector("input").files[0]; reader.readAsDataURL(file) } function getBase64(file) { var reader = new FileReader(); reader.readAsDataURL(file); reader.onload = function () { return reader.result; }; reader.onerror = function (error) { console.log('Error: ', error); }; } async function upload() { var file = document.querySelector('input').files[0]; let result = await getBase64(file) console.log(result); } FileReader se ejecuta de forma asíncrona, por lo que reader.onload no se completa al instante. Devuelve el result antes reader.onload haya terminado, por lo que el result no tiene un valor.
La segunda vez que ejecuta upload , el resultado tiene un valor porque reader.onload ha finalizado. Lo más probable es que el resultado registrado sea el resultado de la llamada anterior para upload .
Puede solucionar esto haciendo que la upload sea una función asíncrona que espere una respuesta de getBase64 . Esto también requerirá que rn el resultado en reader.onload en lugar de establecer el valor globalmente en la etiqueta <script>
La respuesta que ASDFGerte vinculó explica esto, pero lo explicaré en el contexto de su pregunta.
Examinemos lo que sucede:
el usuario hace clic en el botón
la función de carga se ejecuta
getBase64 se llama
crear un lector de archivos y leer el archivo
asignar una función al detector de eventos .onload
asignar una función al detector de eventos .onerror
devuelve el resultado de la variable, que en este momento no existe, porque el evento .onload aún no se ha activado.
Después de su segundo clic, el evento se activó, pero para el resultado anterior, no para un resultado nuevo.
El segundo objetivo es arreglar esto, y mi forma favorita es usar la sintaxis de async await .
echa un vistazo a esta reelaboración de tu código
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Upload</title> </head> <body> <input type="file" id="file"> <button id="button" onclick="upload()">Upload</button> <script type="text/javascript"> async function getBase64(file) { var reader = new FileReader(); reader.readAsDataURL(file); let result; await new Promise(resolve => { reader.onload = function () { result = reader.result; resolve(); }; reader.onerror = function (error) { console.log('Error: ', error); resolve(); }; }); return result; } async function upload() { var file = document.querySelector('input').files[0]; const result = await getBase64(file); console.log(result); } </script> </body> </html>