0

I'm trying to make an api request, to my server where i have some files, that I'm sending along.

I have made an array of custom objects, where i have two parameters, the file extension and the raw data base654 encoded

  onSubmitHandler = (e) =>{
    e.preventDefault()
    const contactRequest = {
        email: this.state.email,
        name: this.state.name,
        message: this.state.message,
        files: this.state.files,
        result: this.state.files.map(file => ({
            "file": this.findFileTypeHandler(file.name), 
            "data": this.getBase64(file)
        }))
    }
    console.log(this.getBase64(this.state.files[0]))
    console.log(contactRequest)
}

the issue is in my getBase64 function

i havde tried several approaches.

    getBase64 = file => {
     let ans  = ''
    var reader = new FileReader();
    reader.readAsDataURL(file);
    reader.onload = function () {
    console.log(reader.result) //logged correctly here, but after undefined is returned
    ans = reader.result
    };
    reader.onerror = function (error) {
      console.log('error is ', error)
      return error;
    };
    return ans;
 }

the correct answer is logged correctly, but it returns undefined first. This is due to It's asynchronous behavior.

Is there a way, so i can make it wait till the function is loaded correctly.

I initially though about making a async await approach, but i think this would get messy, since I'm already planing, to use promises, when i make a post request to my server.

Ating
  • 2,540
  • 1
  • 11
  • 39

1 Answers1

0

Okay here's a simple one. Pass a callback function to the getBase64, and then the callback function will receive the result. Doesn't require that much of a modification:

getBase64 = (file, callBack) => {
    let ans = '';
    var reader = new FileReader();
    reader.readAsDataURL(file);
    reader.onload = () => {
        callBack(reader.result);
    };
    reader.onerror = error => {
        console.log('error is ', error);
        return error;
    };
};

Which you can then use later on as:

getBase64(target, res => console.log(res));

Or if you want the result in a variable, you could do:

let b64;
getBase64(target, res => { b64 = res; });
Predrag Beocanin
  • 1,277
  • 2
  • 16
  • 24
  • yes i tried this initially, and decided to store the answer in a variable, to easier, see where the problem occurs – Ating Jan 25 '19 at 22:17
  • 2
    of course it does, the added `return` returns from the `onload` hander callback function, not the `getBase64()` function. – Randy Casburn Jan 25 '19 at 22:18
  • 1
    Yeah Randy is right, I'm going to run this somewhere real quick and figure out the probable scope issue then, update the answer accordingly. – Predrag Beocanin Jan 25 '19 at 22:19
  • It's not a scope issue, it's an async issue. The return statement in the `onload` is meaningless. Have a look here to understand the issue, https://stackoverflow.com/questions/14220321/how-do-i-return-the-response-from-an-asynchronous-call – Keith Jan 25 '19 at 22:39