Created
May 15, 2018 02:14
-
-
Save evilsoft/38c0bc8ba12508923276cbaf4f19cd31 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const Async = require('crocks/Async') | |
const assign = require('crocks/helpers/assign') | |
const compose = require('crocks/helpers/compose') | |
const isNil = require('crocks/predicates/isNil') | |
const maybeToAsync = require('crocks/Async/maybeToAsync') | |
const not = require('crocks/logic/not') | |
const objOf = require('crocks/helpers/objOf') | |
const prop = require('crocks/Maybe/prop') | |
const safeAfter = require('crocks/Maybe/safeAfter') | |
const tap = require('crocks/helpers/tap') | |
const { fromPromise } = Async | |
// mergeData :: (String, Object) -> a -> Object | |
const mergeData = (label, data) => | |
compose(assign(data), objOf(label)) | |
// Using safeAfter will work on the value of the | |
// "target" or Codomain of a function. so here | |
// we check to see if the result is undefined, | |
// null or NaN. If not return a Just, otherwise | |
// Nothing. | |
// getElemSafe :: String -> Maybe Node | |
const getElemSafe = safeAfter( | |
not(isNil), | |
document.getElementById | |
) | |
// fromPromise wraps a Promise returning function and will | |
// convert it into an Async returning function. This allows | |
// them to be lazily composed with other Asyncs | |
// getUserMedia :: MediaConstraints -> Async Error Stream | |
const getUserMedia = | |
fromPromise(navigator.getUserMedia, navigator) | |
// connectStream :: Object -> Async Error Object | |
const connectStream = data => | |
getUserMedia(data.constraints) | |
.map(mergeData('stream', data)) | |
// addStreamToVideo :: Object -> () | |
const addStreamToVideo = ({ video, stream }) => { | |
video.srcObject = stream | |
} | |
// addVideo :: Object -> Maybe Object | |
const addVideo = data => | |
prop('elemId', data) | |
.chain(getElemSafe) | |
.map(mergeData('video', data)) | |
const flow = data => | |
// Start with an Async, loaded with the head of your | |
// computation. | |
Async.of(data) | |
// Any other Sum type (Maybe, Result, Either) can be | |
// transformed into an Async and chained in. Functions | |
// like tryCatch (which returns a Result if no errors are thrown) | |
// come in very handy | |
.chain(maybeToAsync('video elem not found', addVideo)) | |
// Any function that captures disjunction or an async call | |
// should be chained in to apply those effects. | |
.chain(connectStream) | |
// for working with references (objects, etc) you can tap | |
// and this will signal that something side-effecty is going on | |
// will throw away any return from a tapped function and return | |
// the parameters, which were just mutated (in a side-effect) | |
.map(tap(addStreamToVideo)) | |
flow({ | |
elemId: 'local_video', | |
constraints: { video: true } | |
}).fork(handleErr, handleSucc) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment