Get file contents without a promise

In the file_data_init function I have it take files and put them into a json. Unfortunately when reading it returns late as a promise meaning that the json doesn’t get sent to the next function. Is there any way of fixing this? Can I make the function wait until it’s done and then return the json?

https://replit.com/@HexHands/DataDynamo-Uploading-Fileio?v=1

    function file_data_init(file) {
      
        const reader = new FileReader();
        reader.onload = function(e) {
            const content = e.target.result;
            const customObject = {
                "filepath": file.name,
                "type": file.type,
                "size": file.size / (1024 * 1024),
                "compute": null,
                "fileurl": [],
                "file": content,
                "status": "init"
            };
          console.log(customObject)
            let cond = function() {
               if (!customObject==undefined) {
                 return true;
               }
              waitUntil(cond)
              .then(() => {
                return customObject;
              });

            }
            
            
        };
        reader.readAsDataURL(file);
      
    }
1 Like

If you want to avoid using a Promise and handle it without promises, you can make use of a callback function.

1 Like

You could do as Sky suggested:

function file_data_init(file, callback) {
	const reader = new FileReader();
	reader.onload = function(e) {
		const content = e.target.result;
		const customObject = {
			"filepath": file.name,
			"type": file.type,
			"size": file.size / (1024 * 1024),
			"compute": null,
			"fileurl": [],
			"file": content,
			"status": "init"
		};
		// just call the callback with the data you want
		callback(customObject);
		/* (I'm not sure what's going on with your `waitUntil`
		and your weird boolean check where you compare a `bool`
		to `undefined`) */
	};
	reader.readAsDataURL(file);
}

But in my opinion promises are more elegant:

function file_data_init(file) {
	return new Promise(function(resolve, reject) {
		const reader = new FileReader();
		reader.onload = function(e) {
			const content = e.target.result;
			const customObject = {
				"filepath": file.name,
				"type": file.type,
				"size": file.size / (1024 * 1024),
				"compute": null,
				"fileurl": [],
				"file": content,
				"status": "init"
			};
			// just resolve with the data you want
			resolve(customObject);
		};
		// and reject any errors
		reader.onerror = reject;
		reader.readAsDataURL(file);
	});
}

My problem with promises was that it would still start the next function with an undefined. My wait until logic was suppose to slow it down but ultimately failed.

Why did you need to slow it down?

Because the promise isn’t instantly complete. So if I where to take the response of the promise before it finishes it would be undefined.

If I understand correctly, the issue is that a Promise never returns a value. The way you’re supposed to get a value from a promise is with .then. The function you input into then receives the result as its parameter and only runs once the promise is complete (if an error occurs, catch runs instead).

If you could provide an example of how you use the function and its value I could try and give you a promisified version. :smile:

1 Like

This is what I am currently doing. I just need to call upload_files with the json in a list that is being returned by file_data_init.

    //Base Functions
    function file_data_init(file, callback) {
      const reader = new FileReader();
      reader.onload = function (e) {
        const content = e.target.result;
        const customObject = {
          "filepath": file.name,
          "type": file.type,
          "size": file.size / (1024 * 1024),
          "compute": null,
          "fileurl": [],
          "file": content,
          "status": "init"
        };
        callback(customObject);
      };
      reader.readAsDataURL(file);
    }

    file_data_init(file, function (customObject) {
      
      console.log(customObject);
    });


    //Upload File
    document.getElementById("upload_btn").onclick = async function () {
      await new Promise((resolve) => {
        document.getElementById("fileInput").addEventListener("change", resolve, {once: true});
        document.getElementById("fileInput").click();
    });
      
      const files = Array.from(document.getElementById("fileInput").files);
      const fileList = files.map(file => file_data_init(file));
      upload_files(fileList);
    }
    
    function upload_files(files) {
      for (let file_iterate = 0; file_iterate < files.length; file_iterate++) {
        let file = files[file_iterate];
        console.log(file);
      }
      
      filesjson["key"] = "value"
    }
document.getElementById("upload_btn").onclick = async function () {
	// this is a bit weird, but I guess it works
	await new Promise((resolve) => {
		document.getElementById("fileInput").addEventListener("change", resolve, {once: true});
		document.getElementById("fileInput").click();
	});

	const files = Array.from(document.getElementById("fileInput").files);
	// this is an array of `Promise`s (not the results of that function)
	const fileList = files.map(file => file_data_init(file));
	// there's a handy function perfect for this scenario: `Promise.all`
	Promise.all(fileList)
		.then(upload_files);
}

function upload_files(files) {
	for (let file_iterate = 0; file_iterate < files.length; file_iterate++) {
		let file = files[file_iterate];
		console.log(file);
	}
	filesjson["key"] = "value";
}

Some general advice from personal experience, if you have to ‘slow down’ something, you’re doing it wrong (I don’t mean that as criticism, just advice for the future).

I think you don’t understand Promises very well, which to be honest a lot of people don’t :man_shrugging:

The best way to think of them is what they are named, a ‘promise’. A Promise is a data type that just says eventually some function will be completed and a value will be returned. If you store a Promise directly in a variable, that variable will never be the value of the function that is the promise.

You can only get the value of that function using then. The callback you pass into then is only called when the function inside the Promise finishes, and because of scope, then will be the only way you can get that value.

1 Like

Thanks but I am still having an issue:
ReferenceError: file is not definedhttps://datadynamo-uploading-fileio–hexhands.repl.co/:58
It you would like you can look at all the code:
https://replit.com/@HexHands/DataDynamo-Uploading-Fileio?v=1
Sadly I am not too good at js.

The issue is that you didn’t use the promisified version of the file_data_init function using that snippet I sent above. Once I added that and fixed some minor bugs everything seemed to work in a fork of your Repl I made.

Thanks it works now! Sorry for not being the most understanding.

1 Like

Awesome :tada: Promises are confusing, but once it clicks (and I know my explanantion of promises was terrible) it makes a lot more sense and it can be a lot nicer to use Promises. :smile:

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.