git ssb

0+

dinoworm 🐛 / campjs-viii-ludditejs



Tree:
📄.gitignore
📄LICENSE
📄NOTES.md
📄README.md
📄avatar.png
📁dist
📄enspiral.png
📄example.js
📄index.css
📄index.html
📄index.js
📄luddite.jpg
📄package-lock.json
📄package.json
📁stuff
📁test
README.md

luddite.js


hey CampJS

i'm Mikey (@ahdinosaur) from Enspiral

<div class="row">
<a href="http://dinosaur.is.com">
<img alt="Mikey's avatar" src="./avatar.png" width="200" />
</a>
<a href="http://enspiral.com">
<img alt="Enspiral logo" src="./enspiral.png" width="200" />
</a>
</div>

slides are available at http://dinosaur.is/campjs-viii-ludditejs.

???

second time presenting at a conference.

i might say negative things about some JavaScript patterns, but i use those patterns too.

everyone in the JavaScript community is doing a wonderful job.

apologies in advance if i disguise any opinions as facts.


what?

luddite.js is simple decentralized JavaScript.

???

but really a study of functional JavaScript patterns that have evolved in userland


Luddite?

the Luddites was a political movement against automated centralized technology.

<div style='display: flex; justify-content: center'>
<img src="./luddite.jpg" height='400' />
</div>

???


but JavaScript?

i'm going to talk about

???


simple functional patterns

what if i told you...

that you only needed plain functions and objects?

???


sync function syntax

function fn (...args) { return value }
const fn = (...args) => value

sync function signals

with a sync function, there are two possible signals:

  1. value: return value
  2. error: throw error

???

function fn (...args) { throw error }
try {
  fn(...args)
} catch (const err) {
  // handle error
}

require / module.exports =

const thing = require('module')
module.exports = thing
const { thing: thingy } = require('module')
module.exports = { thing: thingy }

vs: import / export

import thing from 'module'
import { thing as thingy } from 'module'

hyperscript

const h = require('react-hyperscript')

module.exports = Table

function Table ({ rows ) {
  return h('table.table', rows.map(row => {
    h('tr.row', row.map(item => {
      h('td.item', item)
    })
  })
}

???


vs: hyperx

const hyperx = require('hyperx')
const React = require('react')
const html = hyperx(React.createElement)
module.exports = Table

function Table ({ rows ) {
  return html`<table class='table'>
    ${rows.map(row => {
      html`<tr class='row'>
        ${row.map(item => {
          html`<td class='item'>${item}</td>`
        })}
      </tr>`
    })}
  </table>`
}

vs: jsx

const React = require('react')

export default function Table ({ table }) {
  return <table className='table'>
    {table.map(row => {
      <tr className='row'>
        {row.map(item => {
          <td className='item'>{item}</td>
        })}
      </tr>
    })
  </table>
}

redux

reducer:

(state, action) => nextState

???


async function

const request = require('request')
const parallel = require('run-parallel')

module.exports = fetchCats

function fetchCats ({ cats }, cb) {
  return parallel(cats.map(cat => {
    return request(cat, cb)
  }))
})

promise

a "promise" is an eventual value

const promise = new Promise((resolve, reject) => {
  // do stuff...
  resolve(value)
  // or
  reject(error)
}

???

```js
module.exports = fetchCats

function fetchCats ({ cats }) {
  return Promise.all(cats.map(cat => {
    return fetch(cat)
  }))
})

continuable

a "continuable" is a function that takes a single argument, a node-style (error-1st) callback.

const continuable = (cb) => {
  // do stuff...
  cb(null, data)
  // or
  cb(error)
}

???

a continuable is the callback version of a promise

const request = require('request')
const parallel = require('run-parallel')

module.exports = fetchCats

function fetchCats ({ cats }) {
  return cb => parallel(cats.map(cat => {
    return request(cat, cb)
  }))
})

async errors

with a error-first callback, there are three possible signals:

  1. value: cb(null, value)
  2. user error: cb(error)
  3. programmer error: throw error

???

promise errors smush the user and programmer errors together


pull stream

???


source

function values (array) {
  var i = 0
  function read (abort, callback) {
    if (abort || i === array.length) cb(true)
    else cb(null, array[i++]
  }
}

???


sink

function log (read) {
  read(null, function next (err, data) {
    if (err) return console.log(err)
    console.log(data)
    // recursively call read again!
    read(null, next)
  })
}

through

function map (mapper) {
  // a sink function: accept a source
  return function (read) {
    // but return another source!
    return function (abort, cb) {
      read(abort, function (err, data) {
        // if the stream has ended, pass that on.
        if (err) cb(err)
        // apply a mapping to that data
        else cb(null, mapper(data))
      })
    }
  }
}

pull stream errors

with a pull stream source callback, there are four possible signals:

  1. value: cb(null, value)
  2. user error: cb(error)
  3. programmer error: throw error
  4. complete: cb(true)

???


stories


catstack

build a framework alone from scratch

learnings:

???

reinvent all the wheels!


patch ecosystem

build an app with others, bring-your-own framework modules

learnings:

Built with git-ssb-web