Skip to content

Commit

Permalink
Refactor: re-throw error on load (katspaugh#3586)
Browse files Browse the repository at this point in the history
* Refactor: re-throw error on load

* Media event type

* Rm the blob check added in katspaugh#3532
  • Loading branch information
katspaugh committed Mar 9, 2024
1 parent e389ed8 commit 2301646
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 36 deletions.
2 changes: 1 addition & 1 deletion cypress/e2e/error.cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ describe('WaveSurfer error handling tests', () => {
cy.window().its('WaveSurfer').should('exist')

cy.window().then((win) => {
return new Promise((resolve, reject) => {
return new Promise((resolve) => {
win.wavesurfer = win.WaveSurfer.create({
container: '#waveform',
height: 200,
Expand Down
28 changes: 14 additions & 14 deletions src/player.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,25 +31,25 @@ class Player<T extends GeneralEventTypes> extends EventEmitter<T> {
}
// Speed
if (options.playbackRate != null) {
this.onceMediaEvent('canplay', () => {
if (options.playbackRate != null) {
this.media.playbackRate = options.playbackRate
}
})
this.onMediaEvent(
'canplay',
() => {
if (options.playbackRate != null) {
this.media.playbackRate = options.playbackRate
}
},
{ once: true },
)
}
}

protected onMediaEvent(
event: keyof HTMLMediaElementEventMap,
callback: () => void,
options?: AddEventListenerOptions,
protected onMediaEvent<K extends keyof HTMLElementEventMap>(
event: K,
callback: (ev: HTMLElementEventMap[K]) => void,
options?: boolean | AddEventListenerOptions,
): () => void {
this.media.addEventListener(event, callback, options)
return () => this.media.removeEventListener(event, callback)
}

protected onceMediaEvent(event: keyof HTMLMediaElementEventMap, callback: () => void): () => void {
return this.onMediaEvent(event, callback, { once: true })
return () => this.media.removeEventListener(event, callback, options)
}

protected getSrc() {
Expand Down
40 changes: 19 additions & 21 deletions src/wavesurfer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ export type WaveSurferEvents = {
/** Just before the waveform is destroyed so you can clean up your events */
destroy: []
/** When source file is unable to be fetched, decoded, or an error is thrown by media element */
error: []
error: [error: Error]
}

class WaveSurfer extends Player<WaveSurferEvents> {
Expand Down Expand Up @@ -187,7 +187,9 @@ class WaveSurfer extends Player<WaveSurferEvents> {
// of render w/o audio if pre-decoded peaks and duration are provided
const url = this.options.url || this.getSrc() || ''
if (url || (this.options.peaks && this.options.duration)) {
this.load(url, this.options.peaks, this.options.duration)
// Swallow async errors because they cannot be caught from a constructor call.
// Subscribe to the wavesurfer's error event to handle them.
this.load(url, this.options.peaks, this.options.duration).catch(() => null)
}
})
}
Expand Down Expand Up @@ -244,8 +246,8 @@ class WaveSurfer extends Player<WaveSurferEvents> {
this.emit('seeking', this.getCurrentTime())
}),

this.onMediaEvent('error', () => {
this.emit('error')
this.onMediaEvent('error', (err) => {
this.emit('error', err.error)
}),
)
}
Expand Down Expand Up @@ -392,15 +394,6 @@ class WaveSurfer extends Player<WaveSurferEvents> {
if (!blob && !channelData) {
const onProgress = (percentage: number) => this.emit('loading', percentage)
blob = await Fetcher.fetchBlob(url, onProgress, this.options.fetchParams)
.then((blob) => blob)
.catch(() => {
this.emit('error')
return undefined
})
}

if (!blob) {
return
}

// Set the mediaelement source
Expand All @@ -411,7 +404,7 @@ class WaveSurfer extends Player<WaveSurferEvents> {
duration ||
this.getDuration() ||
(await new Promise((resolve) => {
this.onceMediaEvent('loadedmetadata', () => resolve(this.getDuration()))
this.onMediaEvent('loadedmetadata', () => resolve(this.getDuration()), { once: true })
}))

// Set the duration if the player is a WebAudioPlayer without a URL
Expand All @@ -428,11 +421,6 @@ class WaveSurfer extends Player<WaveSurferEvents> {
} else if (blob) {
const arrayBuffer = await blob.arrayBuffer()
this.decodedData = await Decoder.decode(arrayBuffer, this.options.sampleRate)
.then((buffer) => buffer)
.catch(() => {
this.emit('error')
return null
})
}

if (this.decodedData) {
Expand All @@ -445,12 +433,22 @@ class WaveSurfer extends Player<WaveSurferEvents> {

/** Load an audio file by URL, with optional pre-decoded audio data */
public async load(url: string, channelData?: WaveSurferOptions['peaks'], duration?: number) {
await this.loadAudio(url, undefined, channelData, duration)
try {
return await this.loadAudio(url, undefined, channelData, duration)
} catch (err) {
this.emit('error', err as Error)
throw err
}
}

/** Load an audio blob */
public async loadBlob(blob: Blob, channelData?: WaveSurferOptions['peaks'], duration?: number) {
await this.loadAudio('blob', blob, channelData, duration)
try {
return await this.loadAudio('blob', blob, channelData, duration)
} catch (err) {
this.emit('error', err as Error)
throw err
}
}

/** Zoom the waveform by a given pixels-per-second factor */
Expand Down

0 comments on commit 2301646

Please sign in to comment.