1👍
✅
There’s really nothing Vue or TypeScript specific in your question, so I’ll attempt to answer with plain old JavaScript. I’ve included a runnable code snippet.
In a nutshell, whenever the selected files change:
- Create a single
FileReader
instead of one per selected file. - Attach a single
load
event listener, and obtain theFileReader
‘sresult
(the file content). - Read each file, one at a time, waiting for each file to be loaded and read prior to reading the next file.
Were it me, I would make a function to read a file and resolve with the file’s content. You could then call that function from your showFiles
method, and await
the result of each file.
Here’s a runnable example in raw JavaScript. Note that inputFile
corresponds to your fileSelect
reference, and the results
array corresponds to your data
array (which, BTW, should be an array not an object). Also, I’ve wired up the change
event listener in the JS code, but it’s the same as the @change
listener in your template.
(function() {
'use strict'
const inputFile = document.getElementById('inputFile')
// Holds the contents of each selected file.
const results = []
inputFile.addEventListener('change', async e => {
const files = e.target.files
const reader = new FileReader()
// New set of results each time.
results.splice(0)
for (const file of files)
results.push(await readFile(reader, file))
// Do something with the files.
console.log(results)
})
/**
* Read a file asynchronously and resolve with the contents.
*
* @param {FileReader} reader - A FileReader instance that will read `file`
* as text.
* @param {File} file - A selected File instance.
*/
function readFile(reader, file) {
const deferredResult = new Promise(resolve => {
reader.addEventListener('load', function getResult() {
resolve(reader.result)
reader.removeEventListener('load', getResult)
})
})
reader.readAsText(file)
return deferredResult
}
})()
<!doctype html>
<html>
<head>
</head>
<body>
<input multiple type="file" id="inputFile" accept=".json">
</body>
</html>
Source:stackexchange.com