Ajax running before fileReader sequence is grounded

Asked

Viewed 30 times

0

I’m developing a form that can receive multiple images in a file Multiple input field. The method I am using converts these images to Base64, and so sends them via POST to an Hidden input with the value of Base64. However, I’m encountering some problems with ajax and fileReader.

Here follow the codes:

function converte() {
    const imagens = document.getElementById('passeio_imagens').files;
    var x = 0;
    for (var i = 0; i < imagens.length; i++) {
        const reader = new FileReader()
        reader.readAsDataURL(imagens[i]);
        reader.onload = () => {
            $('#form-cadastrar-passeio').append('<input name="imagem' + x + '" type="hidden" value="' + reader.result + '">')
            x++
        }
    }
}
$('#form-cadastrar-passeio').validate({
        rules: {
            nome: 'required',
            preco: 'required',
            duracao: 'required',
            tipo: 'required',
            descricao: 'required',
            endereco: 'required',
            longitude: 'required',
            latitude: 'required'
        },
        submitHandler: (form) => {

            converte()

                $.ajax({
                    url: form.action,
                    type: form.method,
                    data: $(form).serialize(),
                    success: (response) => {
                        console.log(response)
                        const jsonObject = JSON.parse(response)
                        alert(jsonObject.message)

                        if (jsonObject.code === 200) {
                            location.href = '../'
                        }
                    },

                    error: (message) => {
                        alert('Erro ao inserir dados: ' + message)
                    }
                })
            }
        }
    })

The problem I’m having is when the POST comes to PHP, the picture fields, image1... are not received. I suspect it is because the Reader.onload is not finished until the ajax is executed. Would you have some way to ensure that the multiple image Reader.onload ends before running ajax?

1 answer

0

The problem with your code is in this construction:

converte()

$.ajax({ ....

When calling the method converte in turn, there’s this code:

reader.onload = () => {
    $('#form-cadastrar-passeio').append('<input name="imagem' + x + '" type="hidden" value="' + reader.result + '">')
    x++
}

That is, the onload will be executed when the image has been processed, as it is in the documentation here: Filereader/readAsDataURL

When the read operation is finished, the readyState property is updated to DONE, and the loadend (en-US) event is released

To better understand the concept of callback and Promise I suggest reading that other question: Difference between Promise and callback

In your case you are trying to send the form without having the images processed and created the new fields in form. You must wait for this event to occur to have the elements added to form. The example below illustrates this:

function previewFile() {
  const preview = document.querySelector('img');
  const file = document.querySelector('input[type=file]').files[0];
  const reader = new FileReader();

  reader.addEventListener("load", function () {
    console.log("Ponto 1");
    // converter o file de imagem oara uma string de base 64
    preview.src = reader.result;
  }, false);

  if (file) {
    reader.readAsDataURL(file);
  }
  
  // adicionar um handler para quando o load terminar
  reader.addEventListener('loadend', handleEvent);
  
  console.log("Ponto 2");
}

function handleEvent(e) {
    console.log("Ponto 3")
    console.log(`Terniando, ${e.loaded} bytes processados\nJá pode fazer a chamada Ajax`);
    // agora pode aqui fazer a chamada ajax.
};
<input type="file"  multiple="multiple" onchange="previewFile()"><br>
<img src="" height="200" alt="Preview...">

Note that in the output the sequence shown is "Point 2, 1 and 3", that is, ends the Function before going through load and loadend.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.