Skip to content

Commit

Permalink
refactor: turn events into promises
Browse files Browse the repository at this point in the history
turn any once occuring event on any element into a promise. This
pattern is already in use but now abstracted into a function.
  • Loading branch information
gruhn committed Aug 29, 2018
1 parent 8c775d8 commit b8161f1
Show file tree
Hide file tree
Showing 4 changed files with 23 additions and 22 deletions.
11 changes: 5 additions & 6 deletions src/components/QrcodeReader.vue
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import * as Scanner from '../misc/scanner.js'
import Camera from '../misc/camera.js'
import { imageDataFromFile, imageDataFromUrl } from '../misc/image-data.js'
import { hasFired } from '../misc/promisify.js'
import isBoolean from 'lodash/isBoolean'
export default {
Expand Down Expand Up @@ -160,7 +161,7 @@ export default {
}
},
paused (paused) {
async paused (paused) {
const video = this.$refs.video
if (paused) {
Expand All @@ -172,11 +173,9 @@ export default {
video.play()
video.addEventListener(
'timeupdate',
() => { this.readyAfterPause = true },
{ once: true }
)
await hasFired(video, 'timeupdate')
this.readyAfterPause = true
}
},
Expand Down
9 changes: 3 additions & 6 deletions src/misc/camera.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { imageDataFromVideo } from './image-data.js'
import { hasFired } from './promisify.js'

class Camera {

Expand Down Expand Up @@ -41,11 +42,7 @@ export default async function (constraints, videoEl) {
}

const stream = await navigator.mediaDevices.getUserMedia(constraints)

const streamLoadedPromise = new Promise((resolve, reject) => {
videoEl.addEventListener('loadeddata', resolve, { once: true })
videoEl.addEventListener('error', reject, { once: true })
})
const streamLoaded = hasFired(videoEl, 'loadeddata', 'error')

if (videoEl.srcObject !== undefined) {
videoEl.srcObject = stream
Expand All @@ -62,7 +59,7 @@ export default async function (constraints, videoEl) {
videoEl.playsInline = true
videoEl.play() // firefox does not emit `loadeddata` if video not playing

await streamLoadedPromise
await streamLoaded

return new Camera(videoEl, stream)
}
15 changes: 5 additions & 10 deletions src/misc/image-data.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { DropImageFetchError, DropImageDecodeError } from './errors.js'
import { hasFired } from './promisify.js'

const canvas = document.createElement('canvas')
const canvasCtx = canvas.getContext('2d')
Expand Down Expand Up @@ -31,29 +32,23 @@ export async function imageDataFromUrl (url) {
}

const image = document.createElement('img')

const imageLoadedPromise = new Promise((resolve, reject) => {
image.onload = resolve
})
const imageLoaded = hasFired(image, 'load')

image.src = url

await imageLoadedPromise
await imageLoaded

return imageDataFromImage(image)
}

export async function imageDataFromFile (file) {
if (/image.*/.test(file.type)) {
const reader = new FileReader()

const readerLoadedPromise = new Promise((resolve, reject) => {
reader.onload = event => resolve(event.target.result)
})
const readerLoaded = hasFired(reader, 'load')

reader.readAsDataURL(file)

const dataURL = await readerLoadedPromise
const dataURL = (await readerLoaded).target.result

return imageDataFromUrl(dataURL)
} else {
Expand Down
10 changes: 10 additions & 0 deletions src/misc/promisify.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@

export function hasFired (element, successEvent, errorEvent) {
return new Promise((resolve, reject) => {
element.addEventListener(successEvent, resolve, { once: true })

if (errorEvent !== undefined) {
element.addEventListener(errorEvent, reject, { once: true })
}
})
}

0 comments on commit b8161f1

Please sign in to comment.