Turn XMLhttpRequest into a function fails: asynchr

2020-03-31 06:05发布

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?.

2条回答
太酷不给撩
2楼-- · 2020-03-31 06:47

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);
});
查看更多
Fickle 薄情
3楼-- · 2020-03-31 06:59

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);
查看更多
登录 后发表回答