SlideShare a Scribd company logo
1 of 58
ASYNC FRONTIERS
HI, I’M DOMENIC
STANDARDS AS PROTOCOLS
A PROMISE-RETURNING PLATFORM
▪ fetch(…)
▪ navigator.mediaDevices.getUserMedia(…)
▪ fontFace.load()
▪ httpResponseBody.text()
▪ navigator.requestMIDIAccess()
▪ serviceWorkerClient.openWindow(…)
▪ crypto.subtle.encrypt(…)
▪ animation.finished
▪ …
THERE’S MORE TO LIFE THAN PROMISES
singular plural
sync values iterators
async promises ???
singular plural
sync values iterators
async promises ???
THE REAL WORLD IS MORE COMPLICATED
TWO AXES OF INTERESTINGNESS
▪Asynchronicity
▪Pluralness
THE ASYNCHRONOUS FRONTIER
SINGULAR/ASYNC
Quadrant 2
TAMING COMPLEXITY VIA OPINIONS
▪ Promises are eager, not lazy
▪ Continuables a.k.a. “thunks” are a lazy alternative
▪ Instead, we use functions returning promises for laziness
▪ Promises enforce async-flattening
▪ No promises for promises
▪ Troublesome for type systems, but convenient for developers
▪ Promise bake in exception semantics
▪ Could delegate that to another type, e.g. Either<value, error>
▪ But promise semantics integrate well with JS (see async/await)
RESULT, NOT ACTION
Promises represent the eventual result
of an async action; they are not a
representation of the action itself
PROMISES ARE MULTI-CONSUMER
// In one part of your code
awesomeFonts.ready.then(() => {
revealAwesomeContent();
scrollToAwesomeContent();
});
// In another part of your code
awesomeFonts.ready.then(() => {
preloadMoreFonts();
loadAds();
});
CANCELABLE PROMISES (“TASKS”)
▪ Showing up first in the Fetch API
▪ A promise subclass
▪ Consumers can request cancelation
▪ Multi-consumer branching still allowed; ref-counting tracks cancelation
requests
CANCELABLE PROMISES IN ACTION
const fp = fetch(url);
fp.cancel(); // cancel the fetch
const fp2 = fetch(url);
const jp = fp2.then(res => res.json());
jp.cancel(); // cancel either the fetch or the JSON body parsing
const fp3 = fetch(url);
const jp = fp3.then(res => res.json());
const hp = fp3.then(res => res.headers);
jp.cancel(); // nothing happens yet
hp.cancel(); // *now* the fetch could be canceled
CANCELABLE PROMISES IN ACTION
// Every promise gets finally
anyPromise.finally(() => {
doSomeCleanup();
console.log("all done, one way or another!");
});
// Canceled promises *only* get finally triggered
canceled
.then(() => console.log("never happens"))
.catch(e => console.log("never happens"))
.finally(() => console.log("always happens"));
CANCELABLE PROMISES IN ACTION
// All together now:
startSpinner();
const p = fetch(url)
.then(r => r.json())
.then(data => fetch(data.otherUrl))
.then(r => r.text())
.then(text => updateUI(text))
.catch(err => showUIError())
.finally(stopSpinner);
cancelButton.onclick = () => p.cancel();
DESIGN DECISIONS FOR TASKS
▪ Ref-counting, instead of disallowing branching
▪ Cancelation (= third state), instead of abortion (= rejected promise)
▪ Subclass, instead of baking it in to the base Promise class
▪ Evolve promises, instead of creating something incompatible
TASKS ARE IN PROGRESS,
BUT I AM HOPEFUL
PLURAL/SYNC
Quadrant 3
READ-ONLY VS. MUTABLE
▪ Iterator interface
▪ next() → { value, done }
▪ Generator interface
▪ next(v) → { value, done }
▪ throw(e)
▪ return(v)
ITERATORS ARE SINGLE-CONSUMER
▪ Once you next() an iterator, that value is gone forever
▪ If you want a reusable source of iterators, have a function that returns
fresh iterators
▪ Iterables have [Symbol.iterator]() methods that do exactly that
▪ (… except sometimes they don’t)
▪ Is the iterator or the iterable fundamental?
▪ Is the sequence repeatable?
WHERE DO WE ADD METHODS?
▪ myArray.map(…).filter(…).reduce(…) is nice
▪ Can we have that for iterators? Iterables?
▪ Iterators conventionally share a common prototype (but not always)
▪ Iterables do not—could we retrofit one? Probably not…
▪ If we add them to iterators, is it OK that mapping “consumes” the
sequence?
▪ If we add them to iterables, how do we choose between
keys/entries/values?
REVERSE ITERATORS?
▪ You can’t in general iterate backward through an iterator
▪ The iterator may be infinite, or generated from a generator function, …
▪ You can reduce, but not reduceRight
▪ https://github.com/leebyron/ecmascript-reverse-iterable
ITERATORS WORK,
BUT HAVE ROOM TO GROW
PLURAL/ASYNC
Quadrant 4!
WHAT NEEDS ASYNC PLURAL, ANYWAY?
▪ I/O streams
▪ Directory listings
▪ Sensor readings
▪ Events in general
▪ …
AN ITERATOR OF PROMISES? NO
iop.next() // { value: a promise, done: ??? }
iop.next() // { value: a promise, done: ??? }
iop.next() // { value: a promise, done: ??? }
iop.next() // { value: a promise, done: ??? }
ASYNC ITERATORS
https://github.com/zenparsing/async-iteration/
ai.next() // promise for { value, done }
ai.next() // promise for { value, done }
ai.next() // promise for { value, done }
ASYNC ITERATORS
https://github.com/zenparsing/async-iteration/
async for (const x of ai) {
console.log(x);
}
ASYNC ITERATORS
https://github.com/zenparsing/async-iteration/
async function* directoryEntries(path) {
const dir = await opendir(path);
try {
let entry;
while ((entry = await readdir(dir)) !== null) {
yield entry;
}
} finally {
yield closedir(dir);
}
}
THE ASYNC ITERATOR DESIGN
▪ The natural composition of sync iterators and promises; fits well with JS
▪ async for-of
▪ async generators
▪ Single-consumer async iterator, plus async iterables = async iterator
factories (just like for sync)
▪ Consumer-controlled rate of data flow
▪ Request queue of next() calls
▪ Automatic backpressure
▪ Implicit buffering allows late subscription
A SPECIAL CASE OF ASYNC ITERATORS:
I/O STREAMS
READABLE STREAMS
const reader = readableStream.getReader();
reader.read().then(
({ value, done }) => {
if (done) {
console.log("The stream is closed!");
} else {
console.log(value);
}
},
e => console.error("The stream is errored!", e)
);
https://streams.spec.whatwg.org/
READABLE STREAMS
async for (const chunk of readableStream) {
console.log(chunk);
}
https://streams.spec.whatwg.org/
READABLE STREAMS
https://streams.spec.whatwg.org/
readableStream
.pipeThrough(transformStream1)
.pipeThrough(transformStream2)
.pipeTo(writableStream)
.then(() => console.log("All data successfully written!"))
.catch(e => console.error("Something went wrong!", e));
THE READABLE STREAM DESIGN
▪ Focused on wrapping I/O sources into a stream interface
▪ Specifically designed to be easy to construct around raw APIs like kernel read(2)
▪ A variant, ReadableByteStream, with support for zero-copy reads from kernel
memory into an ArrayBuffer.
▪ Exclusive reader construct, for off-main-thread piping
▪ Integrate with writable streams and transform streams to represent the
rest of the I/O ecosystem
▪ Readable streams are to async iterators as arrays are to sync iterators
READABLE STREAMS IN ACTION
ASYNC ITERATORS ARE “PULL”
WHAT ABOUT “PUSH”?
REMEMBER OUR SCENARIOS
▪ I/O streams
▪ Directory listings
▪ Sensor readings
▪ Events in general
▪ …
OBSERVABLES
const subscription = listenFor("click").subscribe({
next(value) { console.log("Clicked button", value) },
throw(error) { console.log("Error listening for clicks", e); },
return() { console.log("No more clicks"); }
});
cancelButton.onclick = () => subscription.unsubscribe();
https://github.com/zenparsing/es-observable
THE OBSERVABLE DESIGN
▪ An observable is basically a function taking { next, return, throw }
▪ The contract is that the function calls next zero or more times, then one of either
return or throw.
▪ You wrap this function in an object so that it can have methods like map/filter/etc.
▪ Observables are to async iterators as continuables are to promises
▪ You can unsubscribe, which will trigger a specific action
▪ Push instead of pull; thus not suited for I/O
▪ No backpressure
▪ No buffering
OBSERVABLE DESIGN CONFUSIONS
▪ Has a return value, but unclear how to propagate that when doing
map/filter/etc.
▪ Tacks on cancelation functionality, but unclear how it integrates with
return/throw, or really anything
▪ Sometimes is async, but sometimes is sync (for “performance”)
PULL TO PUSH IS EASY
try {
async for (const v of ai) {
observer.next(v);
}
} catch (e) {
observer.throw(e);
} finally {
observer.return();
}
PUSH TO PULL IS HARD
Too much code for a slide, but:
▪ Buffer each value, return, or throw from the pusher
▪ Record each next() call from the puller
▪ Correlated them with each other:
▪ If there is a next() call outstanding and a new value/return/throw comes in, use it
to fulfill/reject that next() promise
▪ If there are extra value/return/throws in the buffer and a new next() call comes in,
immediately fulfill/reject and shift off the buffer
▪ If both are empty, wait for something to disturb equilibrium in either direction
IT’S UNCLEAR WHETHER OBSERVABLES
PULL THEIR OWN WEIGHT
BEHAVIORS
const gamepads = navigator.getGamepads();
const sensor = new sensors.AmbientLight({ frequency: 100 });
const bluetooth = doABunchOfWebBluetoothStuff();
requestAnimationFrame(function frame() {
console.log(gamepads[0].axes[0], gamepads[0].axes[1]);
console.log(gamepads[0].buttons[0].pressed);
console.log(sensor.value);
console.log(bluetooth.value);
requestAnimationFrame(frame);
});
BEHAVIOR DESIGN SPACE
▪ Continuous, not discrete (in theory)
▪ Polling, not pulling or pushing
▪ The sequence is not the interesting part, unlike other async plurals
▪ Operators like map/filter/etc. are thus not applicable
▪ Maybe plus, minus, other arithmetic?
▪ min(…behaviors), max(…behaviors), …?
▪ What does a uniform API for these even look like?
▪ Could such an API apply to discrete value changes as well?
THINK ABOUT BEHAVIORS MORE
WRAPPING UP
singular plural
sync
async
values
Either
exceptions
primitives iterators
iterables
generators
reverse iterators
arrays
continuables
promises
tasks
async iterators
streams
observables
behaviors
event emitters
THINGS TO THINK ABOUT
▪ Representing the action vs. representing the result
▪ Lazy vs. eager
▪ Push vs. pull vs. poll
▪ Mutable by consumers vs. immutable like a value
▪ Allow late subscription or not
▪ Multi-consumer vs. single-consumer
▪ Automatic backpressure vs. manual pause/resume
▪ Micro-performance vs. macro-performance
CHECK OUT GTOR
https://github.com/kriskowal/gtor/
SHOULD YOU EVEN CARE?
NONE OF THIS IS URGENT,
EXCEPT WHEN IT IS
THIS IS THE
ASYNC FRONTIER,
AND YOU ARE THE
PIONEERS
Thank you!
@domenic

More Related Content

What's hot

Avoiding callback hell in Node js using promises
Avoiding callback hell in Node js using promisesAvoiding callback hell in Node js using promises
Avoiding callback hell in Node js using promisesAnkit Agarwal
 
Asynchronous programming done right - Node.js
Asynchronous programming done right - Node.jsAsynchronous programming done right - Node.js
Asynchronous programming done right - Node.jsPiotr Pelczar
 
Web Crawling with NodeJS
Web Crawling with NodeJSWeb Crawling with NodeJS
Web Crawling with NodeJSSylvain Zimmer
 
Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...
Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...
Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...Domenic Denicola
 
ES2015 (ES6) Overview
ES2015 (ES6) OverviewES2015 (ES6) Overview
ES2015 (ES6) Overviewhesher
 
Callbacks, promises, generators - asynchronous javascript
Callbacks, promises, generators - asynchronous javascriptCallbacks, promises, generators - asynchronous javascript
Callbacks, promises, generators - asynchronous javascriptŁukasz Kużyński
 
JavaScript - new features in ECMAScript 6
JavaScript - new features in ECMAScript 6JavaScript - new features in ECMAScript 6
JavaScript - new features in ECMAScript 6Solution4Future
 
ECMAScript 6: A Better JavaScript for the Ambient Computing Era
ECMAScript 6: A Better JavaScript for the Ambient Computing EraECMAScript 6: A Better JavaScript for the Ambient Computing Era
ECMAScript 6: A Better JavaScript for the Ambient Computing EraAllen Wirfs-Brock
 
$q and Promises in AngularJS
$q and Promises in AngularJS $q and Promises in AngularJS
$q and Promises in AngularJS a_sharif
 
An Intro To ES6
An Intro To ES6An Intro To ES6
An Intro To ES6FITC
 
Introduction to Ecmascript - ES6
Introduction to Ecmascript - ES6Introduction to Ecmascript - ES6
Introduction to Ecmascript - ES6Nilesh Jayanandana
 
Understanding Asynchronous JavaScript
Understanding Asynchronous JavaScriptUnderstanding Asynchronous JavaScript
Understanding Asynchronous JavaScriptjnewmanux
 
JavaScript Promises
JavaScript PromisesJavaScript Promises
JavaScript PromisesTomasz Bak
 
Explaining ES6: JavaScript History and What is to Come
Explaining ES6: JavaScript History and What is to ComeExplaining ES6: JavaScript History and What is to Come
Explaining ES6: JavaScript History and What is to ComeCory Forsyth
 

What's hot (20)

Avoiding callback hell in Node js using promises
Avoiding callback hell in Node js using promisesAvoiding callback hell in Node js using promises
Avoiding callback hell in Node js using promises
 
Asynchronous programming done right - Node.js
Asynchronous programming done right - Node.jsAsynchronous programming done right - Node.js
Asynchronous programming done right - Node.js
 
Web Crawling with NodeJS
Web Crawling with NodeJSWeb Crawling with NodeJS
Web Crawling with NodeJS
 
JavaScript Promise
JavaScript PromiseJavaScript Promise
JavaScript Promise
 
Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...
Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...
Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...
 
ES2015 (ES6) Overview
ES2015 (ES6) OverviewES2015 (ES6) Overview
ES2015 (ES6) Overview
 
Callbacks, promises, generators - asynchronous javascript
Callbacks, promises, generators - asynchronous javascriptCallbacks, promises, generators - asynchronous javascript
Callbacks, promises, generators - asynchronous javascript
 
JavaScript - new features in ECMAScript 6
JavaScript - new features in ECMAScript 6JavaScript - new features in ECMAScript 6
JavaScript - new features in ECMAScript 6
 
ECMAScript 6
ECMAScript 6ECMAScript 6
ECMAScript 6
 
ECMAScript 6: A Better JavaScript for the Ambient Computing Era
ECMAScript 6: A Better JavaScript for the Ambient Computing EraECMAScript 6: A Better JavaScript for the Ambient Computing Era
ECMAScript 6: A Better JavaScript for the Ambient Computing Era
 
$q and Promises in AngularJS
$q and Promises in AngularJS $q and Promises in AngularJS
$q and Promises in AngularJS
 
Promise pattern
Promise patternPromise pattern
Promise pattern
 
An Intro To ES6
An Intro To ES6An Intro To ES6
An Intro To ES6
 
JavaScript Promises
JavaScript PromisesJavaScript Promises
JavaScript Promises
 
Introduction to Ecmascript - ES6
Introduction to Ecmascript - ES6Introduction to Ecmascript - ES6
Introduction to Ecmascript - ES6
 
Understanding Asynchronous JavaScript
Understanding Asynchronous JavaScriptUnderstanding Asynchronous JavaScript
Understanding Asynchronous JavaScript
 
Promises, Promises
Promises, PromisesPromises, Promises
Promises, Promises
 
JavaScript Promises
JavaScript PromisesJavaScript Promises
JavaScript Promises
 
Explaining ES6: JavaScript History and What is to Come
Explaining ES6: JavaScript History and What is to ComeExplaining ES6: JavaScript History and What is to Come
Explaining ES6: JavaScript History and What is to Come
 
ES6: Features + Rails
ES6: Features + RailsES6: Features + Rails
ES6: Features + Rails
 

Viewers also liked

ES2015 / ES6: Basics of modern Javascript
ES2015 / ES6: Basics of modern JavascriptES2015 / ES6: Basics of modern Javascript
ES2015 / ES6: Basics of modern JavascriptWojciech Dzikowski
 
The State of JavaScript (2015)
The State of JavaScript (2015)The State of JavaScript (2015)
The State of JavaScript (2015)Domenic Denicola
 
Real World Windows 8 Apps in JavaScript
Real World Windows 8 Apps in JavaScriptReal World Windows 8 Apps in JavaScript
Real World Windows 8 Apps in JavaScriptDomenic Denicola
 
Creating Truly RESTful APIs
Creating Truly RESTful APIsCreating Truly RESTful APIs
Creating Truly RESTful APIsDomenic Denicola
 
Introducing Razor - A new view engine for ASP.NET
Introducing Razor - A new view engine for ASP.NET Introducing Razor - A new view engine for ASP.NET
Introducing Razor - A new view engine for ASP.NET Shiju Varghese
 
Razor and the Art of Templating
Razor and the Art of TemplatingRazor and the Art of Templating
Razor and the Art of TemplatingJess Chadwick
 
Angular 2 NgModule
Angular 2 NgModuleAngular 2 NgModule
Angular 2 NgModuleEyal Vardi
 
Routing And Navigation
Routing And NavigationRouting And Navigation
Routing And NavigationEyal Vardi
 
Template syntax in Angular 2.0
Template syntax in Angular 2.0Template syntax in Angular 2.0
Template syntax in Angular 2.0Eyal Vardi
 
Upgrading from Angular 1.x to Angular 2.x
Upgrading from Angular 1.x to Angular 2.xUpgrading from Angular 1.x to Angular 2.x
Upgrading from Angular 1.x to Angular 2.xEyal Vardi
 
Component lifecycle hooks in Angular 2.0
Component lifecycle hooks in Angular 2.0Component lifecycle hooks in Angular 2.0
Component lifecycle hooks in Angular 2.0Eyal Vardi
 
ES6 - Next Generation Javascript
ES6 - Next Generation JavascriptES6 - Next Generation Javascript
ES6 - Next Generation JavascriptRamesh Nair
 
Angular 2.0 Dependency injection
Angular 2.0 Dependency injectionAngular 2.0 Dependency injection
Angular 2.0 Dependency injectionEyal Vardi
 
Angular 2 - Ahead of-time Compilation
Angular 2 - Ahead of-time CompilationAngular 2 - Ahead of-time Compilation
Angular 2 - Ahead of-time CompilationEyal Vardi
 

Viewers also liked (20)

The jsdom
The jsdomThe jsdom
The jsdom
 
ES2015 / ES6: Basics of modern Javascript
ES2015 / ES6: Basics of modern JavascriptES2015 / ES6: Basics of modern Javascript
ES2015 / ES6: Basics of modern Javascript
 
The State of JavaScript (2015)
The State of JavaScript (2015)The State of JavaScript (2015)
The State of JavaScript (2015)
 
Lecture 2: ES6 / ES2015 Slide
Lecture 2: ES6 / ES2015 SlideLecture 2: ES6 / ES2015 Slide
Lecture 2: ES6 / ES2015 Slide
 
Real World Windows 8 Apps in JavaScript
Real World Windows 8 Apps in JavaScriptReal World Windows 8 Apps in JavaScript
Real World Windows 8 Apps in JavaScript
 
Creating Truly RESTful APIs
Creating Truly RESTful APIsCreating Truly RESTful APIs
Creating Truly RESTful APIs
 
The Final Frontier
The Final FrontierThe Final Frontier
The Final Frontier
 
Client-Side Packages
Client-Side PackagesClient-Side Packages
Client-Side Packages
 
Introducing Razor - A new view engine for ASP.NET
Introducing Razor - A new view engine for ASP.NET Introducing Razor - A new view engine for ASP.NET
Introducing Razor - A new view engine for ASP.NET
 
Razor and the Art of Templating
Razor and the Art of TemplatingRazor and the Art of Templating
Razor and the Art of Templating
 
Views
ViewsViews
Views
 
JavaScript on the Desktop
JavaScript on the DesktopJavaScript on the Desktop
JavaScript on the Desktop
 
Angular 2 NgModule
Angular 2 NgModuleAngular 2 NgModule
Angular 2 NgModule
 
Routing And Navigation
Routing And NavigationRouting And Navigation
Routing And Navigation
 
Template syntax in Angular 2.0
Template syntax in Angular 2.0Template syntax in Angular 2.0
Template syntax in Angular 2.0
 
Upgrading from Angular 1.x to Angular 2.x
Upgrading from Angular 1.x to Angular 2.xUpgrading from Angular 1.x to Angular 2.x
Upgrading from Angular 1.x to Angular 2.x
 
Component lifecycle hooks in Angular 2.0
Component lifecycle hooks in Angular 2.0Component lifecycle hooks in Angular 2.0
Component lifecycle hooks in Angular 2.0
 
ES6 - Next Generation Javascript
ES6 - Next Generation JavascriptES6 - Next Generation Javascript
ES6 - Next Generation Javascript
 
Angular 2.0 Dependency injection
Angular 2.0 Dependency injectionAngular 2.0 Dependency injection
Angular 2.0 Dependency injection
 
Angular 2 - Ahead of-time Compilation
Angular 2 - Ahead of-time CompilationAngular 2 - Ahead of-time Compilation
Angular 2 - Ahead of-time Compilation
 

Similar to Async Frontiers

BUILDING APPS WITH ASYNCIO
BUILDING APPS WITH ASYNCIOBUILDING APPS WITH ASYNCIO
BUILDING APPS WITH ASYNCIOMykola Novik
 
Playing With Fire - An Introduction to Node.js
Playing With Fire - An Introduction to Node.jsPlaying With Fire - An Introduction to Node.js
Playing With Fire - An Introduction to Node.jsMike Hagedorn
 
Think Async: Asynchronous Patterns in NodeJS
Think Async: Asynchronous Patterns in NodeJSThink Async: Asynchronous Patterns in NodeJS
Think Async: Asynchronous Patterns in NodeJSAdam L Barrett
 
From Node.js to Design Patterns - BuildPiper
From Node.js to Design Patterns - BuildPiperFrom Node.js to Design Patterns - BuildPiper
From Node.js to Design Patterns - BuildPiperLuciano Mammino
 
Intro to Asynchronous Javascript
Intro to Asynchronous JavascriptIntro to Asynchronous Javascript
Intro to Asynchronous JavascriptGarrett Welson
 
The promise of asynchronous php
The promise of asynchronous phpThe promise of asynchronous php
The promise of asynchronous phpWim Godden
 
Coroutines talk ppt
Coroutines talk pptCoroutines talk ppt
Coroutines talk pptShahroz Khan
 
RxJS In-Depth - AngularConnect 2015
RxJS In-Depth - AngularConnect 2015RxJS In-Depth - AngularConnect 2015
RxJS In-Depth - AngularConnect 2015Ben Lesh
 
The Evolution of Async-Programming on .NET Platform (.Net China, C#)
The Evolution of Async-Programming on .NET Platform (.Net China, C#)The Evolution of Async-Programming on .NET Platform (.Net China, C#)
The Evolution of Async-Programming on .NET Platform (.Net China, C#)jeffz
 
Asynchronous programming patterns in Perl
Asynchronous programming patterns in PerlAsynchronous programming patterns in Perl
Asynchronous programming patterns in Perldeepfountainconsulting
 
Open World Forum 2014 : From ES6 to Javascript 2.0. What use today ? par Jon...
Open World Forum 2014  : From ES6 to Javascript 2.0. What use today ? par Jon...Open World Forum 2014  : From ES6 to Javascript 2.0. What use today ? par Jon...
Open World Forum 2014 : From ES6 to Javascript 2.0. What use today ? par Jon...ALTER WAY
 
What's New in JavaScript
What's New in JavaScriptWhat's New in JavaScript
What's New in JavaScriptDan Cohn
 
Implementing a many-to-many Relationship with Slick
Implementing a many-to-many Relationship with SlickImplementing a many-to-many Relationship with Slick
Implementing a many-to-many Relationship with SlickHermann Hueck
 
Torquebox OSCON Java 2011
Torquebox OSCON Java 2011Torquebox OSCON Java 2011
Torquebox OSCON Java 2011tobiascrawley
 
Future vs. Monix Task
Future vs. Monix TaskFuture vs. Monix Task
Future vs. Monix TaskHermann Hueck
 
The Evolution of Async-Programming (SD 2.0, JavaScript)
The Evolution of Async-Programming (SD 2.0, JavaScript)The Evolution of Async-Programming (SD 2.0, JavaScript)
The Evolution of Async-Programming (SD 2.0, JavaScript)jeffz
 
Top 10 RxJs Operators in Angular
Top 10 RxJs Operators in Angular Top 10 RxJs Operators in Angular
Top 10 RxJs Operators in Angular Jalpesh Vadgama
 

Similar to Async Frontiers (20)

The evolution of asynchronous JavaScript
The evolution of asynchronous JavaScriptThe evolution of asynchronous JavaScript
The evolution of asynchronous JavaScript
 
BUILDING APPS WITH ASYNCIO
BUILDING APPS WITH ASYNCIOBUILDING APPS WITH ASYNCIO
BUILDING APPS WITH ASYNCIO
 
Playing With Fire - An Introduction to Node.js
Playing With Fire - An Introduction to Node.jsPlaying With Fire - An Introduction to Node.js
Playing With Fire - An Introduction to Node.js
 
Think Async: Asynchronous Patterns in NodeJS
Think Async: Asynchronous Patterns in NodeJSThink Async: Asynchronous Patterns in NodeJS
Think Async: Asynchronous Patterns in NodeJS
 
From Node.js to Design Patterns - BuildPiper
From Node.js to Design Patterns - BuildPiperFrom Node.js to Design Patterns - BuildPiper
From Node.js to Design Patterns - BuildPiper
 
Intro to Asynchronous Javascript
Intro to Asynchronous JavascriptIntro to Asynchronous Javascript
Intro to Asynchronous Javascript
 
The promise of asynchronous php
The promise of asynchronous phpThe promise of asynchronous php
The promise of asynchronous php
 
Coroutines talk ppt
Coroutines talk pptCoroutines talk ppt
Coroutines talk ppt
 
RxJS In-Depth - AngularConnect 2015
RxJS In-Depth - AngularConnect 2015RxJS In-Depth - AngularConnect 2015
RxJS In-Depth - AngularConnect 2015
 
The Evolution of Async-Programming on .NET Platform (.Net China, C#)
The Evolution of Async-Programming on .NET Platform (.Net China, C#)The Evolution of Async-Programming on .NET Platform (.Net China, C#)
The Evolution of Async-Programming on .NET Platform (.Net China, C#)
 
Asynchronous programming patterns in Perl
Asynchronous programming patterns in PerlAsynchronous programming patterns in Perl
Asynchronous programming patterns in Perl
 
Open World Forum 2014 : From ES6 to Javascript 2.0. What use today ? par Jon...
Open World Forum 2014  : From ES6 to Javascript 2.0. What use today ? par Jon...Open World Forum 2014  : From ES6 to Javascript 2.0. What use today ? par Jon...
Open World Forum 2014 : From ES6 to Javascript 2.0. What use today ? par Jon...
 
What's New in JavaScript
What's New in JavaScriptWhat's New in JavaScript
What's New in JavaScript
 
Implementing a many-to-many Relationship with Slick
Implementing a many-to-many Relationship with SlickImplementing a many-to-many Relationship with Slick
Implementing a many-to-many Relationship with Slick
 
Torquebox OSCON Java 2011
Torquebox OSCON Java 2011Torquebox OSCON Java 2011
Torquebox OSCON Java 2011
 
ECMAScript 2015 Tips & Traps
ECMAScript 2015 Tips & TrapsECMAScript 2015 Tips & Traps
ECMAScript 2015 Tips & Traps
 
Future vs. Monix Task
Future vs. Monix TaskFuture vs. Monix Task
Future vs. Monix Task
 
The Evolution of Async-Programming (SD 2.0, JavaScript)
The Evolution of Async-Programming (SD 2.0, JavaScript)The Evolution of Async-Programming (SD 2.0, JavaScript)
The Evolution of Async-Programming (SD 2.0, JavaScript)
 
Plack - LPW 2009
Plack - LPW 2009Plack - LPW 2009
Plack - LPW 2009
 
Top 10 RxJs Operators in Angular
Top 10 RxJs Operators in Angular Top 10 RxJs Operators in Angular
Top 10 RxJs Operators in Angular
 

More from Domenic Denicola

How to Win Friends and Influence Standards Bodies
How to Win Friends and Influence Standards BodiesHow to Win Friends and Influence Standards Bodies
How to Win Friends and Influence Standards BodiesDomenic Denicola
 
Unit Testing for Great Justice
Unit Testing for Great JusticeUnit Testing for Great Justice
Unit Testing for Great JusticeDomenic Denicola
 
Understanding the Node.js Platform
Understanding the Node.js PlatformUnderstanding the Node.js Platform
Understanding the Node.js PlatformDomenic Denicola
 

More from Domenic Denicola (8)

ES6 in Real Life
ES6 in Real LifeES6 in Real Life
ES6 in Real Life
 
Streams for the Web
Streams for the WebStreams for the Web
Streams for the Web
 
After Return of the Jedi
After Return of the JediAfter Return of the Jedi
After Return of the Jedi
 
The State of JavaScript
The State of JavaScriptThe State of JavaScript
The State of JavaScript
 
How to Win Friends and Influence Standards Bodies
How to Win Friends and Influence Standards BodiesHow to Win Friends and Influence Standards Bodies
How to Win Friends and Influence Standards Bodies
 
The Extensible Web
The Extensible WebThe Extensible Web
The Extensible Web
 
Unit Testing for Great Justice
Unit Testing for Great JusticeUnit Testing for Great Justice
Unit Testing for Great Justice
 
Understanding the Node.js Platform
Understanding the Node.js PlatformUnderstanding the Node.js Platform
Understanding the Node.js Platform
 

Recently uploaded

CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):comworks
 
Pigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food ManufacturingPigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food ManufacturingPigging Solutions
 
Human Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsHuman Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsMark Billinghurst
 
Streamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupStreamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupFlorian Wilhelm
 
"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii SoldatenkoFwdays
 
costume and set research powerpoint presentation
costume and set research powerpoint presentationcostume and set research powerpoint presentation
costume and set research powerpoint presentationphoebematthew05
 
Benefits Of Flutter Compared To Other Frameworks
Benefits Of Flutter Compared To Other FrameworksBenefits Of Flutter Compared To Other Frameworks
Benefits Of Flutter Compared To Other FrameworksSoftradix Technologies
 
Connect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationConnect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationSlibray Presentation
 
SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024Scott Keck-Warren
 
Bluetooth Controlled Car with Arduino.pdf
Bluetooth Controlled Car with Arduino.pdfBluetooth Controlled Car with Arduino.pdf
Bluetooth Controlled Car with Arduino.pdfngoud9212
 
Transcript: New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024Transcript: New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024BookNet Canada
 
Install Stable Diffusion in windows machine
Install Stable Diffusion in windows machineInstall Stable Diffusion in windows machine
Install Stable Diffusion in windows machinePadma Pradeep
 
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 3652toLead Limited
 
Scanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsScanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsRizwan Syed
 
Unblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesUnblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesSinan KOZAK
 
Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024Enterprise Knowledge
 
Unleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubUnleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubKalema Edgar
 
Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Scott Keck-Warren
 
My INSURER PTE LTD - Insurtech Innovation Award 2024
My INSURER PTE LTD - Insurtech Innovation Award 2024My INSURER PTE LTD - Insurtech Innovation Award 2024
My INSURER PTE LTD - Insurtech Innovation Award 2024The Digital Insurer
 

Recently uploaded (20)

CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):
 
Pigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food ManufacturingPigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food Manufacturing
 
Human Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsHuman Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR Systems
 
Streamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupStreamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project Setup
 
"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko
 
costume and set research powerpoint presentation
costume and set research powerpoint presentationcostume and set research powerpoint presentation
costume and set research powerpoint presentation
 
Hot Sexy call girls in Panjabi Bagh 🔝 9953056974 🔝 Delhi escort Service
Hot Sexy call girls in Panjabi Bagh 🔝 9953056974 🔝 Delhi escort ServiceHot Sexy call girls in Panjabi Bagh 🔝 9953056974 🔝 Delhi escort Service
Hot Sexy call girls in Panjabi Bagh 🔝 9953056974 🔝 Delhi escort Service
 
Benefits Of Flutter Compared To Other Frameworks
Benefits Of Flutter Compared To Other FrameworksBenefits Of Flutter Compared To Other Frameworks
Benefits Of Flutter Compared To Other Frameworks
 
Connect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationConnect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck Presentation
 
SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024
 
Bluetooth Controlled Car with Arduino.pdf
Bluetooth Controlled Car with Arduino.pdfBluetooth Controlled Car with Arduino.pdf
Bluetooth Controlled Car with Arduino.pdf
 
Transcript: New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024Transcript: New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024
 
Install Stable Diffusion in windows machine
Install Stable Diffusion in windows machineInstall Stable Diffusion in windows machine
Install Stable Diffusion in windows machine
 
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
 
Scanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsScanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL Certs
 
Unblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesUnblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen Frames
 
Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024
 
Unleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubUnleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding Club
 
Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024
 
My INSURER PTE LTD - Insurtech Innovation Award 2024
My INSURER PTE LTD - Insurtech Innovation Award 2024My INSURER PTE LTD - Insurtech Innovation Award 2024
My INSURER PTE LTD - Insurtech Innovation Award 2024
 

Async Frontiers

  • 4. A PROMISE-RETURNING PLATFORM ▪ fetch(…) ▪ navigator.mediaDevices.getUserMedia(…) ▪ fontFace.load() ▪ httpResponseBody.text() ▪ navigator.requestMIDIAccess() ▪ serviceWorkerClient.openWindow(…) ▪ crypto.subtle.encrypt(…) ▪ animation.finished ▪ …
  • 5. THERE’S MORE TO LIFE THAN PROMISES
  • 6. singular plural sync values iterators async promises ???
  • 7. singular plural sync values iterators async promises ???
  • 8. THE REAL WORLD IS MORE COMPLICATED
  • 9. TWO AXES OF INTERESTINGNESS ▪Asynchronicity ▪Pluralness
  • 12. TAMING COMPLEXITY VIA OPINIONS ▪ Promises are eager, not lazy ▪ Continuables a.k.a. “thunks” are a lazy alternative ▪ Instead, we use functions returning promises for laziness ▪ Promises enforce async-flattening ▪ No promises for promises ▪ Troublesome for type systems, but convenient for developers ▪ Promise bake in exception semantics ▪ Could delegate that to another type, e.g. Either<value, error> ▪ But promise semantics integrate well with JS (see async/await)
  • 13. RESULT, NOT ACTION Promises represent the eventual result of an async action; they are not a representation of the action itself
  • 14. PROMISES ARE MULTI-CONSUMER // In one part of your code awesomeFonts.ready.then(() => { revealAwesomeContent(); scrollToAwesomeContent(); }); // In another part of your code awesomeFonts.ready.then(() => { preloadMoreFonts(); loadAds(); });
  • 15. CANCELABLE PROMISES (“TASKS”) ▪ Showing up first in the Fetch API ▪ A promise subclass ▪ Consumers can request cancelation ▪ Multi-consumer branching still allowed; ref-counting tracks cancelation requests
  • 16. CANCELABLE PROMISES IN ACTION const fp = fetch(url); fp.cancel(); // cancel the fetch const fp2 = fetch(url); const jp = fp2.then(res => res.json()); jp.cancel(); // cancel either the fetch or the JSON body parsing const fp3 = fetch(url); const jp = fp3.then(res => res.json()); const hp = fp3.then(res => res.headers); jp.cancel(); // nothing happens yet hp.cancel(); // *now* the fetch could be canceled
  • 17. CANCELABLE PROMISES IN ACTION // Every promise gets finally anyPromise.finally(() => { doSomeCleanup(); console.log("all done, one way or another!"); }); // Canceled promises *only* get finally triggered canceled .then(() => console.log("never happens")) .catch(e => console.log("never happens")) .finally(() => console.log("always happens"));
  • 18. CANCELABLE PROMISES IN ACTION // All together now: startSpinner(); const p = fetch(url) .then(r => r.json()) .then(data => fetch(data.otherUrl)) .then(r => r.text()) .then(text => updateUI(text)) .catch(err => showUIError()) .finally(stopSpinner); cancelButton.onclick = () => p.cancel();
  • 19. DESIGN DECISIONS FOR TASKS ▪ Ref-counting, instead of disallowing branching ▪ Cancelation (= third state), instead of abortion (= rejected promise) ▪ Subclass, instead of baking it in to the base Promise class ▪ Evolve promises, instead of creating something incompatible
  • 20. TASKS ARE IN PROGRESS, BUT I AM HOPEFUL
  • 22. READ-ONLY VS. MUTABLE ▪ Iterator interface ▪ next() → { value, done } ▪ Generator interface ▪ next(v) → { value, done } ▪ throw(e) ▪ return(v)
  • 23. ITERATORS ARE SINGLE-CONSUMER ▪ Once you next() an iterator, that value is gone forever ▪ If you want a reusable source of iterators, have a function that returns fresh iterators ▪ Iterables have [Symbol.iterator]() methods that do exactly that ▪ (… except sometimes they don’t) ▪ Is the iterator or the iterable fundamental? ▪ Is the sequence repeatable?
  • 24. WHERE DO WE ADD METHODS? ▪ myArray.map(…).filter(…).reduce(…) is nice ▪ Can we have that for iterators? Iterables? ▪ Iterators conventionally share a common prototype (but not always) ▪ Iterables do not—could we retrofit one? Probably not… ▪ If we add them to iterators, is it OK that mapping “consumes” the sequence? ▪ If we add them to iterables, how do we choose between keys/entries/values?
  • 25. REVERSE ITERATORS? ▪ You can’t in general iterate backward through an iterator ▪ The iterator may be infinite, or generated from a generator function, … ▪ You can reduce, but not reduceRight ▪ https://github.com/leebyron/ecmascript-reverse-iterable
  • 26. ITERATORS WORK, BUT HAVE ROOM TO GROW
  • 28. WHAT NEEDS ASYNC PLURAL, ANYWAY? ▪ I/O streams ▪ Directory listings ▪ Sensor readings ▪ Events in general ▪ …
  • 29. AN ITERATOR OF PROMISES? NO iop.next() // { value: a promise, done: ??? } iop.next() // { value: a promise, done: ??? } iop.next() // { value: a promise, done: ??? } iop.next() // { value: a promise, done: ??? }
  • 30. ASYNC ITERATORS https://github.com/zenparsing/async-iteration/ ai.next() // promise for { value, done } ai.next() // promise for { value, done } ai.next() // promise for { value, done }
  • 32. ASYNC ITERATORS https://github.com/zenparsing/async-iteration/ async function* directoryEntries(path) { const dir = await opendir(path); try { let entry; while ((entry = await readdir(dir)) !== null) { yield entry; } } finally { yield closedir(dir); } }
  • 33. THE ASYNC ITERATOR DESIGN ▪ The natural composition of sync iterators and promises; fits well with JS ▪ async for-of ▪ async generators ▪ Single-consumer async iterator, plus async iterables = async iterator factories (just like for sync) ▪ Consumer-controlled rate of data flow ▪ Request queue of next() calls ▪ Automatic backpressure ▪ Implicit buffering allows late subscription
  • 34. A SPECIAL CASE OF ASYNC ITERATORS: I/O STREAMS
  • 35. READABLE STREAMS const reader = readableStream.getReader(); reader.read().then( ({ value, done }) => { if (done) { console.log("The stream is closed!"); } else { console.log(value); } }, e => console.error("The stream is errored!", e) ); https://streams.spec.whatwg.org/
  • 36. READABLE STREAMS async for (const chunk of readableStream) { console.log(chunk); } https://streams.spec.whatwg.org/
  • 38. THE READABLE STREAM DESIGN ▪ Focused on wrapping I/O sources into a stream interface ▪ Specifically designed to be easy to construct around raw APIs like kernel read(2) ▪ A variant, ReadableByteStream, with support for zero-copy reads from kernel memory into an ArrayBuffer. ▪ Exclusive reader construct, for off-main-thread piping ▪ Integrate with writable streams and transform streams to represent the rest of the I/O ecosystem ▪ Readable streams are to async iterators as arrays are to sync iterators
  • 40. ASYNC ITERATORS ARE “PULL”
  • 42. REMEMBER OUR SCENARIOS ▪ I/O streams ▪ Directory listings ▪ Sensor readings ▪ Events in general ▪ …
  • 43. OBSERVABLES const subscription = listenFor("click").subscribe({ next(value) { console.log("Clicked button", value) }, throw(error) { console.log("Error listening for clicks", e); }, return() { console.log("No more clicks"); } }); cancelButton.onclick = () => subscription.unsubscribe(); https://github.com/zenparsing/es-observable
  • 44. THE OBSERVABLE DESIGN ▪ An observable is basically a function taking { next, return, throw } ▪ The contract is that the function calls next zero or more times, then one of either return or throw. ▪ You wrap this function in an object so that it can have methods like map/filter/etc. ▪ Observables are to async iterators as continuables are to promises ▪ You can unsubscribe, which will trigger a specific action ▪ Push instead of pull; thus not suited for I/O ▪ No backpressure ▪ No buffering
  • 45. OBSERVABLE DESIGN CONFUSIONS ▪ Has a return value, but unclear how to propagate that when doing map/filter/etc. ▪ Tacks on cancelation functionality, but unclear how it integrates with return/throw, or really anything ▪ Sometimes is async, but sometimes is sync (for “performance”)
  • 46. PULL TO PUSH IS EASY try { async for (const v of ai) { observer.next(v); } } catch (e) { observer.throw(e); } finally { observer.return(); }
  • 47. PUSH TO PULL IS HARD Too much code for a slide, but: ▪ Buffer each value, return, or throw from the pusher ▪ Record each next() call from the puller ▪ Correlated them with each other: ▪ If there is a next() call outstanding and a new value/return/throw comes in, use it to fulfill/reject that next() promise ▪ If there are extra value/return/throws in the buffer and a new next() call comes in, immediately fulfill/reject and shift off the buffer ▪ If both are empty, wait for something to disturb equilibrium in either direction
  • 48. IT’S UNCLEAR WHETHER OBSERVABLES PULL THEIR OWN WEIGHT
  • 49. BEHAVIORS const gamepads = navigator.getGamepads(); const sensor = new sensors.AmbientLight({ frequency: 100 }); const bluetooth = doABunchOfWebBluetoothStuff(); requestAnimationFrame(function frame() { console.log(gamepads[0].axes[0], gamepads[0].axes[1]); console.log(gamepads[0].buttons[0].pressed); console.log(sensor.value); console.log(bluetooth.value); requestAnimationFrame(frame); });
  • 50. BEHAVIOR DESIGN SPACE ▪ Continuous, not discrete (in theory) ▪ Polling, not pulling or pushing ▪ The sequence is not the interesting part, unlike other async plurals ▪ Operators like map/filter/etc. are thus not applicable ▪ Maybe plus, minus, other arithmetic? ▪ min(…behaviors), max(…behaviors), …? ▪ What does a uniform API for these even look like? ▪ Could such an API apply to discrete value changes as well?
  • 53. singular plural sync async values Either exceptions primitives iterators iterables generators reverse iterators arrays continuables promises tasks async iterators streams observables behaviors event emitters
  • 54. THINGS TO THINK ABOUT ▪ Representing the action vs. representing the result ▪ Lazy vs. eager ▪ Push vs. pull vs. poll ▪ Mutable by consumers vs. immutable like a value ▪ Allow late subscription or not ▪ Multi-consumer vs. single-consumer ▪ Automatic backpressure vs. manual pause/resume ▪ Micro-performance vs. macro-performance
  • 57. NONE OF THIS IS URGENT, EXCEPT WHEN IT IS
  • 58. THIS IS THE ASYNC FRONTIER, AND YOU ARE THE PIONEERS Thank you! @domenic

Editor's Notes

  1. I’m here to talk to you about async frontiers. Now why would I be qualified to talk about something like that?
  2. I wrote the spec for ES6 promises, and Promises/A+ before them I’ve spent the last couple years working to bring I/O streams to the browser, from Node.js I’m on TC39, the committee responsible for evolving the JavaScript language And my day job is as an engineer at Google, working on all this stuff
  3. One common question asked about promises is “why standardize them into the language when they could just be a library?” It’s a very good question, that gets to the heart of what standards are about. And the answer is very simple: we standardize promises for the same reasons we standardize HTTP, or HTML, or JSON, or anything else---to give us a shared protocol that everyone can speak, and that future work---both in the browser and in your code---can build on as a basis.
  4. This protocol has spread throughout the platform: we now have a unifying way for the web platform to communicate asynchronous results. And your code can buy into this rich ecosystem as well, by using promises.
  5. But promises are not the only protocol for the platform, of course. Another common protocol is the iterator protocol, which we’ve seen a bit in the preceding talk. This protocol is important for things like JS’s built-in maps and sets, but also for more exotic things on the platform like collections of headers, cookies, query string fragments, and so on. Protocols are everywhere.
  6. From here, having introduced promises and iterators, the standard spiel is to show you this diagram, and declare that I have come to tell you about the amazing unifying abstraction that will save you all from the fires of async-plural hell. Maybe I would even promise you that this magical solution will be standardized in ES2016, and you should all start writing code with it as soon as possible since otherwise you’ll be left behind as all the cool kids rush off into the rapture.
  7. No. This chart is oversimplified to the extreme. It is the product of lazy thinking. And filling in that fourth box won’t solve all your problems.
  8. What’s wrong with that chart aren’t the headings---async/sync, singular/plural. What’s wrong with the chart is pretending that we have only one answer for each of them. Even singular, synchronous values come in different varieties: In languages like C++, you have the distinction of pointer-like vs. object-like; In JavaScript, we have primitives vs. objects vs. some future “value types” proposal; We can further distinguish how our singular, synchronous values handle errors: do we use bubbling exceptions, or some monad-like Either type, etc. So instead of thinking about your problem space as divided up into four neat little boxes, with a single paradigm for each …
  9. … I want you to think about the different ways in which your problems can become interesting, and think about these as two of them. With this perspective, it should become clear that each of these lends itself to more and more interesting possibilities for solutions---iterators and promises are not the only game in town. And when you combine the two, then things get really interesting.
  10. And that’s what today’s talk is really about. I want you to leave this with an appreciation for the rich world of possibilities out there, and the efforts being made to push the boundaries of what’s possible today to explore the frontier of where we’ll be tomorrow. I want you to understand the subtleties involved, the tradeoffs, and all of the other interesting things that make us the kind of software engineers who gather together on a Friday for a conference about code.
  11. Let’s begin by dipping back in to the world of single, async values. We’ve seen a lot about these already today, talking about promises. But let’s try to come at this from a fresh perspective, not taking promises as they are, but instead considering this design space as a whole. What choices do promises make, within the design space of single, async values?
  12. We know that any movement away from the already-complicated singlular/sync quadrant will add complexity. And one of the ways to tame that complexity is to make opinionated decisions about how things should work. Here I’ve given an overview of the opinions that went in to the design of promises---the opinions that helped us narrow down one particular primitive in the async/singular space. (Read.) There’s one more design decision I’ve left off this list, and it’s perhaps the most interesting.
  13. In particular, what this means is that you treat them much like you treat a singular synchronous value---you can pass it around, give it to multiple consumers, and they can all observe it and use it and do whatever they want.
  14. Of course, none of these consumers can interfere with the value. And there’s no semantic where, if one consumer looks at the value, others can’t. Thinking of promises as analogous to synchronous values, that’d be crazy. So you can see why we designed promises so they can be used this way. But it turns out that this isn’t always the most useful approach. Sometimes you want something that’s kind of in between---it should represent the value, for most cases, but also give you a representation of the action that produced that value. And in particular, one important thing you could do to that action, would be to cancel it.
  15. Introducing cancelable promises. (read)
  16. On this last point, in particular we didn’t split into two objects, one representing the action and one representing the value.
  17. We need them sooner rather than later; these should be arriving pretty soon. So although this is part of the frontier, we hope to make it settled territory pretty soon. --- Enough about promises, and everything adjacent to them in the design space. Let’s take a minute…
  18. … and briefly talk about the third quadrant: plural, synchronous sequences. Again, I don’t want to rehash how iterators work for you: I want us to step back and look at the space with fresh eyes, to see what are all the design choices that’ve been made.
  19. The ES spec contains both interfaces: many iterables are simply read-only, with a next() method to get their next value. But those produced by generator functions allow consumers to impact the sequence, including to terminate it with either a return value or an exception. Adding this kind of flexibility to generator functions was specifically done to allow the more … creative use cases, like the spawn function we saw earlier. But it means that consumers can interfere with the sequence, if they want. That’s probably OK though, because…
  20. One the one hand, the iterator is clearly where all the action happens. On the other hand, we talk about maps and sets and arrays more often than we talk about MapIterators or SetIterators or ArrayIterators.
  21. There’s a proposal for a second protocol, reverse iterators, that would allow this. Is such a protocol worth building in to the language?
  22. OK, so we’ve already seen how quadrants 2 and 3 are not as simple as they might first appear. Let’s take our newfound perspective and apply it to the tougher problem, of quadrant 4.
  23. The problem with this idea is that if you have an iterator, you can call next() on it any time---in this example, we call it four times in a row. But, how does the iterator know what it should put for done? It doesn’t even know how long the sequence is, since it still has async work to do!
  24. The async iterator design merges the two concepts in a manner that works out a bit better: instead of next() returning { value, done }, now next() returns a promise for { value, done }. This allows the iterator to asynchronously decide not only the value, but also whether the sequence has ended or not.
  25. Now, it’s important to remember that the async iterator design is speculative. It’s just a proposal. But one thing that’s already a standard, and is already shipping in Chrome in fact, is I/O streams. The interface is a little bit different, for reason we’ll see:
  26. But you can notice the main similarity: each chunk of data from the stream is represented by a promise for a { value, done } pair. There’s this extra reader thing that’s going on, and that’s actually pretty important. But if async iterators take off as a proposal, then we’ll definitely add the extra stuff to readable streams such that you can treat them just like async iterators:
  27. … i.e., using async for-of. Which is great, when you want to consume the stream directly. But really, most of the time when doing I/O, what you actually want to do is set up a chain of transforms, and pipe things to some eventual destination:
  28. … and that’s what the readable stream API is designed around, most of the time. That reader thing I mentioned is specifically designed so that you can pipe a readable stream to a writable stream off the main thread of your app, when you use this kind of code. So you can see we’re actually operating at a somewhat different level here.
  29. To recap some of the highlights of how we designed readable streams, …
  30. Finally, I want to show you … … OK. So enough about streams. Let’s take a step back.
  31. So far we’ve looked at async iterators, which are what naturally emerges when you combine iterators and promises. What’s interesting about them is that, like sync iterators, they are “pull”: the consumer calls next(), and decides when it’s ready for more data. This gives you all those nice things like buffering and backpressure and so on, automatically.
  32. But is there ever a case where “push” is appropriate? Where the consumer gets data pushed to them, as fast as the producer decides to give it?
  33. Let’s look back to our scenarios where async plural might come in handy. Those first three are pretty clearly driven by the consumer: the consumer gets data from a stream when they are ready for it; the consumer asks for the next directory listing or sensor reading as appropriate. But what about “events in general”? By this I mean things like clicks, or mouse moves, or so on. It kind of makes sense to say that a better model for them is that the producer pushes the events. Instead of a consumer asking for a mouse click, they get pushed a mouse click when it happens. Normally we’d use an event emitter for this kind of thing, and we’ll talk about that later. But there’s another approach that’s being proposed, which is this construct called observables.
  34. The code for using an observable looks like this, in its essence. An observable has a subscribe method, which takes this three-method object and returns you a subscription, which you can later use to unsubscribe. Pretty simple:
  35. The next question I have is, given something like an async iterable, can we convert it to an observable? Well, sure: just drain the async iterable as fast as you can, and push the data elsewhere. The code basically looks like this.
  36. It’s certainly doable, but it also raises a lot of hard questions about e.g. what if my buffer gets too full? Various observable frameworks have offered solutions to this, e.g. Dart has pause and resume methods that you have to call manually, RxJS has approximately 30 different methods that produce different variants of observables and things called “subjects” and so on. But in the end it’s just much harder to go in this direction. So my overall thoughts on observables …
  37. … are that it’s unclear whether they pull their own weight to contribute to the async-plural problem space. They have a lot of shortcomings and confusing design choices, whereas async iterators are simple and natural, and can easily be converted to a push model for when that’s appropriate. Performance is often claimed as a benefit, since after all they are just wrappers over functions. But demos with even the most high-frequency events, like mousemove, show that this is not borne out in practice. And in reality, most of your performance will be gained by respecting backpressure and otherwise integrating well with the I/O subsystem.
  38. There’s a final category of async-plural that I want to quickly throw out there, for two reasons. First, it’s pretty different from the other stuff we’ve been seeing. And second, because it’s actually showing up a lot in the platform recently. We call it a “behavior,” adopting some FRP terminology. The basic idea behind a behavior is that you’re measuring a single quantity, repeatedly. So instead of a logical sequence of values, where e.g. if you concatenated them all you’d get something meaningful, it’s the same conceptual value, changing over time. We have here three examples from current or upcoming specs…
  39. I think this is a really fascinating space. When I wrote my talk description, I wasn’t even aware of this as a pattern. It caught me by surprise to see these popping up everywhere, and IMO we as a community haven’t spent enough time on this. Can we fit them into some other abstraction like observables? Should we?
  40. Well … yes, in the sense that this stuff is fun to think about, and will make you a more fulfilled human being. And no, in that at the end of the day, events will continue to work just fine, and you’ll get your job done even if someone makes a mistake and chooses observables over behaviors or whatever.
  41. What I mean by this is that most of the time it’s really OK that the web platform doesn’t have a beautiful compositional paradigm for reactive programming, and instead we just fall back to events. Except sometimes it isn’t---sometimes we’re stuck without a way to stream data that doesn’t occupy all of our memory, so we work to standardize streams. Right now we don’t have a way to cancel our HTTP requests, so we need to finish standardizing tasks. But the rest of it isn’t that big a deal. As long as we have the streams API, I can do streaming HTTP uploads and downloads. I might have to use a while loop and some promises instead of an async for-of loop, but that’s OK.