How to capture FileReader base64 as variable?

I work by this Code

   async function checkFileBase64(el) {
        let inputEl = $(el).find('input[type=file]');
        let promise = getBase64(inputEl[0]);
        return await promise;
    }
    function getBase64(file) {
       return new Promise(function (resolve, reject) {
            let reader = new FileReader();
            reader.onload = function () { resolve(reader.result); };
            reader.onerror = reject;
            reader.readAsDataURL(file.files[0]);
        });
    }

FileReader.readAsDataURL() is asynchronous - the download happens in the background while the rest of the code keeps executing. So the reason console.log(my_pdf_file_as_base64); prints an empty string is that the line my_pdf_file_as_base64 = e.target.result hasn't been executed yet: the call to getBase64() finishes almost immediately, and the subsequent statement is executed; only later (when the download is complete) will the callback be executed.

The way to handle this is to place the code that uses the downloaded file inside the callback:

getBase64(my_pdf_file, function(e) {
    my_pdf_file_as_base64 = e.target.result;
    console.log(my_pdf_file_as_base64);
});

Alternatively, you can repeatedly (e.g. inside a setTimeout callback or inside some DOM event handler) check if reader.readyState === FileReader.DONE - whenever this becomes true, reader.result will contain the file.

A more flexible approach is to use a Promise, which is an object that encapsulates an asynchronous computation:

function getBase64(file, onLoadCallback) {
    return new Promise(function(resolve, reject) {
        var reader = new FileReader();
        reader.onload = function() { resolve(reader.result); };
        reader.onerror = reject;
        reader.readAsDataURL(file);
    });
}

var promise = getBase64(my_pdf_file);
promise.then(function(result) {
    console.log(result);
});

So far, this looks pretty similar to the first solution, but the advantage is that promise is an object that you can pass around to other functions, so that you can start a computation in one place and decide in another place what should happen when it's finished.

As you have probably noticed, neither of these approaches allow you to block further code execution until the file content has been assigned to the global variable my_pdf_file_as_base64. This is by design; however, if you really really need to block on the download because you don't have time to refactor old code, see the discussion in https://stackoverflow.com/a/39914235/626853. If your users' browsers are sufficiently modern, you can use async/await:

$(document).on("click", ".clicker", async function() {
    var promise = getBase64(my_pdf_file);
    var my_pdf_file_as_base64 = await promise;
}

(Note that await only works inside async functions, so your click handler must be async. I also experimented with adding a busy waiting loop, but that caused my browser to hang.)

(Also note, from Charles Owen in a comment, that readAsDataURL actually returns a data: URL, so if you want to get only the Base64 data, you need to strip a prefix as per the linked documentation.)