0

I try to turn an XMLHttpRequest into a function such

var getImageBase64 = function (url) { // code function
    var xhr = new XMLHttpRequest(url); 
    ... // code to load file 
    ... // code to convert data to base64
    return wanted_result; // return result of conversion
}
var newData = getImageBase64('http://fiddle.jshell.net/img/logo.png'); // function call
doSomethingWithData($("#hook"), newData); // reinjecting newData in wanted place.

I'am successful to load the file, and to convert to base64. I'am however consistenly failling to get the result as an output :

var getImageBase64 = function (url) {
    // 1. Loading file from url:
    var xhr = new XMLHttpRequest(url);
    xhr.open('GET', url, true); // url is the url of a PNG image.
    xhr.responseType = 'arraybuffer';
    xhr.onload = function(e) { 
        if (this.status == 200) { // 2. When loaded, do:
            console.log("1:Response?> " + this.response); // print-check xhr response 
            var imgBase64 = converterEngine(this.response); // converter
        }
    }
    xhr.send();
    return xhr.onload(); // <fails> to get imgBase64 value as the function's result.
}

console.log("4>>> " + getImageBase64('http://fiddle.jshell.net/img/logo.png') ) // THIS SHOULD PRINT THE BASE64 CODE (returned resukt of the function  getImageBase64)

See Fiddle here.

How to make it works so it return the new data as output ?


Solution: my final implementation is visible here, and on JS: how to load a bitmap image and get its base64 code?.

Community
  • 1
  • 1
Hugolpz
  • 17,296
  • 26
  • 100
  • 187
  • Yes, that’s how asynchronous things work. Calling `onload` manually does not make the request actually load. You could pass a callback to `getImageBase64` and call it back in `onload`, or return [a promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise). – Ry- Jul 24 '14 at 16:50

2 Answers2

1

Asynchronous calls in JavaScript (like xhr) can't return values like regular functions. The common pattern used when writing asynchronous functions is this:

function asyncFunc(param1, param2, callback) {
  var result = doSomething();
  callback(result);
}

asyncFunc('foo', 'bar', function(result) {
  // result is what you want
});

So your example translated looks like this:

var getImageBase64 = function (url, callback) {
    var xhr = new XMLHttpRequest(url); 
    ... // code to load file 
    ... // code to convert data to base64
    callback(wanted_result);
}
getImageBase64('http://fiddle.jshell.net/img/logo.png', function(newData) {
  doSomethingWithData($("#hook"), newData);
});
doughsay
  • 326
  • 3
  • 11
1

When you use xhr.onload your actually defining a function for JS to call when it loads, hence the value of xhr.onload is the function not the output of the function. Returning xhr.onload() will call that function and return the output, but your onload function has no return statement and hence no output. Additionally you are calling xhr.onload synchronously as you set up the object, and hence it won't have any data to process.

I suggest you add a callback parameter to your function like so, this will execute when the data has loaded.

function getImageBase64( url, callback) {
    // 1. Loading file from url:
    var xhr = new XMLHttpRequest(url);
    xhr.open('GET', url, true); // url is the url of a PNG image.
    xhr.responseType = 'arraybuffer';
    xhr.callback = callback;
    xhr.onload = function(e) { 
        if (this.status == 200) { // 2. When loaded, do:
            console.log("1:Response?> " + this.response); // print-check xhr response 
            var imgBase64 = converterEngine(this.response); // converter
            this.callback(imgBase64);//execute callback function with data
        }
    }
    xhr.send();
}

Then you would use it like so

var myCallBack = function(data){
    alert(data);
};
getImageBase64('http://fiddle.jshell.net/img/logo.png', myCallBack);
nepeo
  • 509
  • 2
  • 9
  • I try to get the resulting value of my function `getImageBase64()` out if it. But `var res = getImageBase64('http://fiddle.jshell.net/img/logo.png', myCallBack);` is still not my new data. – Hugolpz Jul 24 '14 at 17:27
  • The output of the function will not be the response data, there is no return statement anymore. You can store the processed data in the xhr object and return that, but as this is an async call you'll have to wait for the callback to fire before you can access the data anyway. Did you try the example code? The data parameter in the callback is what you want your variable to be. – nepeo Jul 25 '14 at 08:17