Extending on the above solutions by adding, with a use case where I required
the ability to iterate through multiple fields on a form and get their values
and with one being a file, it caused problems with he async requirements
Solved it like this:
    async collectFormData() {
        // Create the file parsing promise
        const toBase64 = file => new Promise((resolve, reject) => {
            const reader = new FileReader();
            reader.readAsDataURL(file);
            reader.onload = () => resolve(reader.result);
            reader.onerror = error => reject(error);
        });
    
        
        let form_vals = []
        let els = [] // Form elements collection
        // This is separate because wrapping the await in a callback
        // doesn't work 
        $(`.form-field`).each(function (e) {
            els.push(this) // add to the collection of form fields
        })
        // Loop through the fields to collect information 
        for (let elKey in els) {
            let el = els[elKey]
            // If the field is input of type file. call the base64 parser
            if ($(el).attr('type') == 'file') {
                // Get a reference to the file
                const file = el.files[0];
                form_vals.push({
                    "key": el.id,
                    "value": await toBase64(file)
                })
        }
        // TODO: The rest of your code here form_vals will now be 
        // populated in time for a server post
    }
This is purely to solve the problem of dealing with multiple fields
in a smoother way