Recursion can get a little ugly. You should wrap them in promises, and use new es6 await/async syntax:
function readValues(filename) {
  return new Promise((resolve) => {
      const reader = new FileReader();
      const file = $(`#${filename}`)[0].files[0];
      reader.readAsDataURL(file);
      reader.onloadend = function() {
        resolve(reader.result.slice(reader.result.indexOf(',')+1));
      };
  });
}
async function main() {
    let results = {};
    for(let x = 19; x < 29; x++) {
      if(values[x]) {
        results[x] = await readValues(keys[x]);
      }
    }
    insertAll(results);
}
main();
For reading all the files at the same time, I recommend using Promise.all:
function readValues(filename) {
  return new Promise((resolve) => {
      const reader = new FileReader();
      const file = $(`#${filename}`)[0].files[0];
      reader.readAsDataURL(file);
      reader.onloadend = function() {
        resolve(reader.result.slice(reader.result.indexOf(',')+1));
      };
  });
}
async function main() {
  let promises = [];
  let results = {};
  for(let x = 19; x < 29; x++) {
    if(values[x]) {
      const task = readValues(keys[x])
                      // Assign the values in results
                      .then(res => results[x] = res);
      promises.push(task);
    }
  }
  await Promise.all(promises);
  // Results is now an object that you can use.
  insertAll(results);
}
main();