So i noticed everytime i paste some file, if i have more than 1 file on my clipboard area it only pastes 1 file, the others my code just don't process.
Here is the snippet to reproduce, even if i have more than 1 file on clipboard it only inserts 1 item in the array. I'm trying to figure out what is happening. (use image files to test).
const inputFileToBase64 = file => new Promise((resolve, reject) => {
const reader = new FileReader()
reader.readAsDataURL(file)
reader.onload = () => resolve(reader.result)
reader.onerror = error => reject(error)
})
const getBase64Files = async (items) => {
const base64Files = []
for (const item of items) {
const base64 = await inputFileToBase64(item.getAsFile())
base64Files.push(base64)
}
return base64Files
}
document.addEventListener('paste', async (event) => {
console.log('pasted')
const items = event.clipboardData.items
const files = await getBase64Files(items)
console.log(files)
})
PASTE HERE
The DataTransferItemList
items
seems to be consumed as soon as the event loop allows it to; it doesn't wait for a FileReader
to read it. So, by the time the first file is read, items
is empty.
If you allow the task queue to do its stuff, even with a setTimeout
of 0, you lose all files:
const items = event.clipboardData.items
await new Promise(resolve => setTimeout(resolve, 0)) //wait 0ms
const files = await getBase64Files(items) //no items, no files
and that's also happening with the working version of getBase64Files
below.
Regardless of the explanation (which one might improve upon), it is always a good idea to start all reading at the same time and await for all to complete:
const getBase64Files = async (items) => {
const base64Files = []
await Promise.allSettled(
Array.from(items).map(
item => inputFileToBase64(item.getAsFile()).then(
file => base64Files.push(file)
)
)
)
return base64Files
}
and that works.