a little class for combining behavior, layout and style

2018-08-02

I don't use Javascript frameworks, so React appeals to me. I like how it organizes ideas. I like its top-down, one-way flow of data. But I also think some of its usefulness is debatable. It has a big island of tooling that's going in a very different direction than the rest of the web. Like Coffeescript or jQuery, in 5 years it will probably inspire standards bodies with its best features.

I also like Web Components, they're great because they offer true, native encapsulation  —  no hacks. They are mostly the result of consensus among the web's working groups. But they're awkward, and already feel outdated. They also only work well in Chrome.

img

I'd like to introduce Tonic. It's about 150 lines of code. It combines some of the goals and ideas of React and Web Components. It works in all browsers. Its intented to provide the minimum of what is needed to organize application code, the flow of data and accommodate component based architecture.

You can find the core library here and a collection of components here on Github.

What are javascript then-ables

async / await improves program flow and reduces the number of callbacks in your code. The await keyword can be used to pause the current code path and wait for an async function to return a value without blocking the event loop.

async function main () {
  console.log('started')
  await sleep(100)
  console.log('finished')
}

main()

An implementation for the sleep function might look like this...

const sleep = n => new Promise(r => setTimeout(r, n))

However, as this example demonstrates, the code in the promise starts executing immediately. Promises are eager (as opposed to being lazy), and sometimes we want them to be lazy. Here is a detailed explaination of why an eager promise may not be what you want.

A then-able is lazy. It has no constructor. It's any function, object or class that implements a then method.

Await-able Classes

To create an async class, implement a then method on it!

class Foo {
  then (resolve, reject) {
    resolve(42)
  }
}

async function main () {
  const answer = await new Foo()
  // answer === 42
}
main()

Await-able Objects

You can do the same thing with an object. You can name the callback functions whatever you want. Also, you aren't required to use or care about the rejection callback.

const Foo = {
  then (resolve) {
    setTimeout(() => resolve(42), 1024)
  }
}

async function main () {
  const answer = await Foo
  // answer === 42
}
main()

Await-able object factories

const Foo = num => ({
  then (resolve) {
    setTimeout(() => resolve(num), 1024)
  }
})

async function main () {
  const answer = await Foo(42)
}
main()

Async then-ables

Object and class methods can use the async keyword, just like functions.

const Foo = {
  async then (resolve) {
    resolve(await request('https://foo.com'))
  }
}

Destructuring assignments provide a way to return multiple values...

class Foo {
  then (resolve) {
    request('https://foo.com', (err, res) => resolve({ err, res }))
  }
}

async function main () {
  const { err, res } = await new Foo

  // More than one err? Const is block-scoped!
  {
    const { err, res } = await new Foo
  }

  // Destructured values can also be aliased.
  const { err: namedError, res: namedResponse } = await new Foo
}
main()

illustrated lamport timestamp

A Lamport Timestamp can be used to determine the order of events in a distributed system. They are a useful primitive when you're building peer-to-peer applications and you want to thread together datasets from different sources.

Clocks vs. Logical Clocks

Why don't we use regular time stamps? Most clocks count time at different rates and experience failures that require resynchronization. This means they are reliably unreliable for determining the order of events.

Lamport Timestamps use a Logical Clock to keep track of the order of events on each node. A logical clock is not a clock that keeps track of the time, it's a monotonically increasing counter. So, when a node in a network receives a message, it re-synchronizes its counter (its clock) with the node that sent the message.

Example

Node A increments its clock before each event that hapens. An event is something meaningful, like when it creates some data. When node A eventually sends its payload over the network, it will include the current value of its clock.

let clock = 0

//
// A thread-safe, monotonically increasing function.
//
function createTimeStamp () {
  clock += 1
  return clock 
}

function doSomething (data) {
  //
  // Do something with some data.
  //
  return {
    data,
    clock: createTimeStamp()
  }
}

//
// Eventually send the data to the network.
//
sendToNetworkQueue(doSomething({ ... }))

When node B receives a message from node A, it will decide how to set its own clock. If the clock value in the message is greater than its own value, it will use the value in the message. Otherwise it will use its own value. In either case, it will also increment its own clock by 1.

let clock = 0

//
// Eventually receive some data from the network.
//
receiveFromNetworkQueue (message) {
  clock = Math.max(message.clock, clock) + 1
}

Here we semi-randomly fail to always tell the other node about the event that happened, illustrating what happens when a node is eventually synchronized.

This may not be the correct primitive for all your use cases. For example, Lamport Timestamps don't express causality, meaning, the reason why one event happened before another isn't in scope of this soluton, but that is something that can be achieved using a Vector Clock.


Special thanks to Fedor Indutny and Feross Aboukhadijeh for reviewing this post. ♥

CODE

GITHUB

https://github.com/hxoht

PUBLIC KEY


Curriculum Vitae

Personal

Name: Paolo Fragomeni, Software Engineer

Contact

Email: hello@hx.ht

Web: https://hx.ht

Twitter: https://twitter.com/hxoht

Github: https://github.com/hxoht

Summary

I Left MIT in 2010 to co-found Nodejitsu (a PaaS, since integrated with GoDaddy). Most recently I founded Voltra Co. (entertainment software) which joined Conductor Lab. In addition to being a technical founder, CTO and engineer I have worked in the infosec space.

Expertise

Computer Science Research. Software Engineering: programming design and engineering, concurrent and distributed programming, metaprogramming, functional programming and ECMAScript (Javascript). Key-Value store

Experience

CTO, Cofounder at Voltra Co.

January 2016 - Augest 2018 (2.5 years)

Voltra Co. was a cloud storage service and set of audio products. Voltra's desktop and mobile players sync so you can stream your music from anywhere. The only ad-free fully hi-res platform. On this project I worked with Electron, JavaScript, Node.js, C++, CSS3, HTML5, Stylus, Jade, Webpack, React, React-Native, and Amazon Web Services. Voltra joined Conductor Lab in Augest 2018.

VP of Engineering at Now Secure

November 2014 - January 2016 (1 year 3 months)

Built engineering and security research teams. Coordinated engineering and research teams. Set technical goals, worked hands on on lots of projects. On this project I worked primarily with C, C++, JavaScript, Node.js, HTML5.

Engineer, CTO at Mic

January 2014 - November 2014 (11 months)

Hereishow.to joined mic.com where I served as CTO. Built an engineering team and integrated components of Here Is How into existing products. On this project I worked with Amazon Web Services, Node.js JavaScript, HTML5, CSS3.

Engineer, CTO, Cofounder at Here Is How

November 2012 - January 2014 (1 year 3 months)

A CMS for technical writing, a web based interface similar to Medium.com. This project was acqui-hired by mic.com On this project I worked with Docker, JavaScript, Node.js, Websockets, C, C++, HTML5, CSS3.

Engineer, CTO, Cofounder at Nodejitsu

September 2010 - December 2012 (2 years 4 months)

Co-Founder, Chief Technology Officer. Lots of R&D. Conceptualized and implemented products that simplify and manage application deployments for the node.js platform.

01 Reykjavik

I stayed in Reykjavik for 3 days. It's a nice quiet place to read a book and collect your thoughts.

02 03 04 01 05 06

The city is walkable. The water is always close. The air and the water seem really clean. Go to a geothermal spa, it's good for you.

07

If you are coming from the US or the EU, just divide by 100 and the bills will make more sense. Food, drinks, everything is about the same price. There is no tipping in Iceland. They'll just try to give it back to you.

08

I had some incredible locally made chocolate. The food in general is pretty diverse and it's not hard to find.

09 10

Aside from MAT, one of my favorite food experiences was the Hlemmur Food Hall. And next to it was The Noodle Station. This place has a solid formula.

Bismút was definitely my favorite place for a cup of coffee, after that probably Kaffihús Vesturbæjar.

11 12

Reykjavik also has places that sell things other than wool sweaters — but I'm not sure for how much longer.

The locals are friendly and very genuine. Reykjavik is small. It's a one street town. There is very little infrastructure. There is no train into the city, so you either take a bus for an hour or a taxi for 150+ euros. Don't be in a hurry.