Skip to content

Instantly share code, notes, and snippets.

@nathanshelly
Last active July 6, 2019 22:27
Show Gist options
  • Save nathanshelly/21d48899354d55c371d1b111440f09c6 to your computer and use it in GitHub Desktop.
Save nathanshelly/21d48899354d55c371d1b111440f09c6 to your computer and use it in GitHub Desktop.
/**
* Note: This file is primarily an experiment (and therefore not necessarily the
* best way to accomplish file reading). Specifically it's an experiment on
* using a parameter-based constructor instead of the more imperative form given
* by the official FileReader API. Basically an experiment to write this:
*
* ```javascript
* const reader = constructFileReader({
* handlers: {
* onload: () => {},
* }
* })
* ```
*
* instead of this:
*
* ```javascript
* const reader = new FileReader()
* reader.onload = () => {}
*
* ```
*
* Literally that's it.
*
* For reference here is the actual official FileReader API
* https://developer.mozilla.org/en-US/docs/Web/API/FileReader
*/
// TODO: write tests? not convinced they're necessary here
// wrap a handler function to bring a FileReader instance into scope
type FileReaderHandlerWrapper = (reader: FileReader) => () => void
// see docs on handlers here
// https://developer.mozilla.org/en-US/docs/Web/API/FileReader#Event_handlers
type FileReaderHandlers = {
onload?: FileReaderHandlerWrapper
onabort?: FileReaderHandlerWrapper
onerror?: FileReaderHandlerWrapper
}
// parameter to construct a FileReader
// currently only supports three handlers, could be expanded to match the full
// FileReader API if needed
type FileReaderOptions = {
handlers: FileReaderHandlers
}
/**
* Construct a FileReader from the given options
*
* Avoid thinking about imperative code and just get your FileReader back 😃
*
* @param options - the possible options for the FileReader, see
* FileReaderOptions type for more
* @returns a FileReader instance
*/
export const constructFileReader = (options: FileReaderOptions): FileReader => {
// construct filereader to convert uploaded file to form usable by WaveSurfer
const reader = new FileReader()
// assign handlers to `reader` object, replicates `reader.on<event> = handler`
if (options.handlers) {
Object.entries(options.handlers).forEach(
([methodName, method]) =>
(reader[
// tell Typescript that each `methodName` is contained in the keys of
// FileReaderOptions
methodName as keyof FileReaderHandlers
// also tell Typescript that the values from Object.entries must be
// defined (again not sure why Typescript doesn't infer this)
] = (method as FileReaderHandlerWrapper)(reader)),
)
}
return reader
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment