13

I have two functions: one that turn files into dataUrl and another that returns a promise with the result:

fileToDataURL(file) { var reader = new FileReader() return new Promise(function (resolve, reject) { reader.onload = function (event) { resolve(event.target.result) } reader.readAsDataURL(file) }) } getDataURLs (target) { // target => <input type="file" id="file"> return Promise.all(target.files.map(fileToDataURL)) } 

target.files.map returns: TypeError: target.files.map is not a function. H

How to modify getDataUrls so it returns an array with the dataUrls?

2 Answers 2

30
function getDataURLs(target) { // target => <input type="file" id="file"> return Promise.all([...target.files].map(fileToDataURL)) } 

FileList is not an Array, and does not inherit from Array, but it does implement the iterable protocol, so you can use the spread syntax to get it as an array.

In case you're wondering how to check if a class like FileList supports the spread syntax, you can do this:

console.log(FileList.prototype[Symbol.iterator]);

If that returns a function (which it does), then that returned function is a generator function that is invoked on an instance of the class by the spread syntax.

Sign up to request clarification or add additional context in comments.

4 Comments

Well I've provided links on things that may be unclear. Hopefully following them should clarify everything I'm covering.
Why did you use Promise.all in your example? Why not using just [...target.files].map ? Is there any benefits using promises over array?
@MohamedAbdallah Promise.all() takes an iterable of promises and returns a single promise which resolves to an array. Read the question, Promise.all() is used there as well, it's not just in my answer. FYI Promise.all() is extremely trivial to google.
My question wasn't what is Promise.all(), it was what the benefit for that case over normal array. BTW thank you, your answer saved my day.
5

While Patrick Roberts' answer is true, you may face an issue on TypeScript:

issue screenshot

Type 'FileList' is not an array type or a string type. Use compiler option '--downlevelIteration' to allow iterating of iterators. ts(2569)

You can find a complete answer about --downlevelIteration the post Why downlevelIteration is not on by default?.

In our case, to iterate on a FileList, instead of the spread operator, use Array.from():

function getDataURLs(target) { // target => <input type="file" id="file"> return Promise.all(Array.from(target.files).map(fileToDataURL)) } 

1 Comment

There is a typo in the code - it has an extra ] character. It should be: return Promise.all(Array.from(target.files).map(fileToDataURL))

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.