Skip to content

Commit

Permalink
first commit
Browse files Browse the repository at this point in the history
  • Loading branch information
Stephen Belanger committed Feb 25, 2019
0 parents commit c1b0ffb
Show file tree
Hide file tree
Showing 19 changed files with 498 additions and 0 deletions.
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
.DS_Store
node_modules
package-lock.json
dist
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# async-iterator-talk

These are the slides for a talk on async iterators at VanJS on February 27th, 2019.
6 changes: 6 additions & 0 deletions assets/about.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
module.exports = {
"name": "Stephen Belanger",
"github": "https://github.com/qard",
"twitter": "https://twitter.com/stephenbelanger",
"work": "Node.js APM Agent Developer at Elastic"
}
23 changes: 23 additions & 0 deletions assets/async-iterator-pipe.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
async function pipeStream (iterator, stream) {
for await (let chunk of iterator) {
stream.write(chunk)
}
stream.end()
}

function pipeDirect (source, target) {
if (target.write && target.end) {
pipeStream(source, target)
return target
} else if (typeof target === 'function') {
return target(source)
} else {
throw new Error('Unrecognized target type')
}
}

function pipe (source, ...transforms) {
return transforms.reduce(pipeDirect, source)
}

module.exports = pipe
44 changes: 44 additions & 0 deletions assets/batching.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
function timeout (ms) {
return new Promise(done => setTimeout(done, ms))
}

async function* numbers () {
let n = 0
while (true) {
await timeout(10)
yield n++
}
}

async function* take (iterator, n) {
while (n-- !== 0) {
const item = await iterator.next()
if (!item.done) yield item.value
}
}

async function toArray (iterator) {
const items = []
for await (let item of iterator) {
items.push(item)
}
return items
}

async function* batch (iterator, size) {
while (true) {
const page = take(iterator, size)
const slice = await toArray(page)
if (!slice.length) break
yield slice
}
}

function sum (items) {
return items.reduce((m, v) => m + v, 0)
}

const batches = batch(numbers(), 8)
for await (let slice of take(batches, 10)) {
console.log(sum(slice))
}
19 changes: 19 additions & 0 deletions assets/custom-async-iterator.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
function interval (ms) {
const iterator = {
async next () {
await timeout(ms)
return {
value: Date.now(),
done: false
}
}
}

const generator = {
[Symbol.asyncIterator] () {
return iterator
}
}

return generator
}
15 changes: 15 additions & 0 deletions assets/http-iterator.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
const Channel = require('channel-surfer')

module.exports = function httpIterator (server) {
const channel = new Channel()

server.on('request', (request, response) => {
channel.give({ request, response })
})

server.on('close', () => {
channel.close()
})

return channel
}
10 changes: 10 additions & 0 deletions assets/http-server.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
const http = require('http')
const httpIterator = require('http-iterator')

const server = http.createServer()
server.listen(3000)

const requests = httpIterator(server)
for await (let { response } of requests) {
response.end('hello world')
}
16 changes: 16 additions & 0 deletions assets/interval.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
function timeout (ms) {
return new Promise(done => {
setTimeout(done, ms)
})
}

async function* interval (ms) {
while (true) {
await timeout(ms)
yield Date.now()
}
}

for await (let time of interval(1000)) {
console.log(time)
}
9 changes: 9 additions & 0 deletions assets/iterable-http-requests.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
const toIter = require('http-iterator')
const http = require('http')

const server = http.createServer()
server.listen(3000)

for await (let { response } of toIter(server)) {
response.end('hello world')
}
43 changes: 43 additions & 0 deletions assets/pagination.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
const pageList = [
{
items: [
{ name: 'first' },
{ name: 'second' }
]
},
{
items: [
{ name: 'third' },
{ name: 'fourth' }
]
}
]

async function loadPage (n) {
await timeout(100) // Simulate async
return pageList[n]
}

async function* getPages () {
let n = 0
let page

while ((page = await loadPage(n++))) {
yield page
}
}

async function* pagesToItems (pages) {
for await (let page of pages) {
for (let item of page.items) {
yield item
}
}
}

const pages = getPages()
const items = pagesToItems(pages)

for await (let item of items) {
console.log(item.name)
}
45 changes: 45 additions & 0 deletions assets/stream-line-split.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
const pipe = require('async-iterator-pipe')

async function* lineSplit (iterator) {
let buffer = ''
for await (let chunk of iterator) {
buffer += chunk.toString()
let position = buffer.indexOf('\n')
while (position >= 0) {
yield buffer.slice(0, position)
buffer = buffer.slice(position + 1)
position = buffer.indexOf('\n')
}
}
}

async function* csv (iterator) {
let keys
for await (let line of iterator) {
const values = line.split(',')
if (!keys) {
keys = values
} else {
const data = {}
for (let i = 0; i < values.length; i++) {
data[keys[i]] = values[i]
}
yield data
}
}
}

async function* toJSON (iterator) {
for await (let item of iterator) {
yield JSON.stringify(item)
}
}

const fs = require('fs')
pipe(
fs.createReadStream('./assets/test.csv'),
lineSplit,
csv,
toJSON,
process.stdout
)
16 changes: 16 additions & 0 deletions assets/stream-transforms.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
const pipe = require('async-iterator-pipe')
const zlib = require('zlib')

async function* upper (iterator) {
for await (let item of iterator) {
yield item.toString().toUpperCase()
}
}

pipe(
process.stdin,
zlib.createGunzip(),
upper,
zlib.createGzip(),
process.stdout
)
11 changes: 11 additions & 0 deletions assets/streams.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
async function concat (stream) {
const chunks = []
for await (let chunk of stream) {
chunks.push(chunk)
}
return Buffer.concat(chunks)
}

const body = await concat(
fs.createReadStream(__filename)
)
3 changes: 3 additions & 0 deletions assets/test.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
key,value
foo,bar
baz,buz
16 changes: 16 additions & 0 deletions code-surfer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import React from 'react'
import { CodeSurfer } from "mdx-deck-code-surfer"
import vsDarkPlus from "prism-react-renderer/themes/vsDarkPlus"

const CustomCodeSurfer = ({ title, code, steps }) => (
<CodeSurfer
title={title}
code={code}
lang="javascript"
showNumbers={false}
theme={vsDarkPlus}
steps={steps}
/>
)

export default CustomCodeSurfer
11 changes: 11 additions & 0 deletions now.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"version": 2,
"name": "async-iterators-a-new-future-for-streams",
"alias": "async-iterators-talk.now.sh",
"builds": [
{
"src": "package.json",
"use": "@now/static-build"
}
]
}
22 changes: 22 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"name": "async-iterator-talk",
"version": "1.0.0",
"description": "VanJS talk about async iterators and streams",
"scripts": {
"start": "mdx-deck slides.mdx",
"build": "npm run build:presentation && npm run build:assets",
"build:presentation": "mdx-deck build slides.mdx --no-html",
"build:assets": "cp -r assets dist/",
"now-build": "npm run build",
"deploy": "now"
},
"author": "Stephen Belanger <[email protected]> (https://github.com/qard)",
"license": "MIT",
"devDependencies": {
"mdx-deck": "^1.8.2",
"mdx-deck-code-surfer": "^0.5.5",
"now": "^13.1.3",
"prism-react-renderer": "^0.1.5",
"raw-loader": "^1.0.0"
}
}
Loading

0 comments on commit c1b0ffb

Please sign in to comment.