- first release 24 december 2009 (jashkena)
- lots of features made it into ECMAScript (
=>
,class
, …) - v2 = community release (2017):
await
, JSX, … - new features = TC39 Stage 4 (
BigInt
→`1n`
)
my_fun = (modes,{define},more...) ->
for a in modes
define a, more...
- Litterate CoffeScript (Markdown)
Calcule un carré
----------------
square = (x) -> x*x
for a in [0..10] by 2
assert a % 2 is 0
cat =
name: 'kitty'
color: 'beige'
for own k,v of cat
console.log "cat has #{v} #{k}"
- warning:
of
in CS isin
in JS
- generator: object with
.next()
→{value,done}
- generator function: returns a generator
f = -> yield 42
v = f()
v.next()
→ { value: 42, done: false }
v.next()
→ { value: 42, done: false }
natural = ->
num = 0
loop
num += 1
yield num
return
perfectCubes = ->
for num from natural()
yield num*num*num
return
do ->
for v from perfectCubes()
console.log v
- warning:
from
in CS isof
in JS
- Promise: object with
.then( on_success, on_failure )
p = Promise.resolve 6
p.then (value) -> assert value is 6
p = new Promise (resolve) ->
# compute, compute
resolve 7
return
p.then (value) -> assert value is 7
p = new Promise.reject new Error 'oops'
p.catch (error) -> assert error.message is 'oops'
await
will interrupt execution and wait for the Promise to resolve
f = ->
value = await Promise.resolve 42
assert value is 42
f()
- shortest useful Promise
sleep = (timeout) -> new Promise (resolve) -> setTimeout resolve, timeout
do ->
console.log 'Ready?'
await sleep 1000
console.log 'Done.'
- async function: function that returns a Promise
f = -> Promise.resolve 42
f().then (value) -> assert value is 42
- a function containing
await
is itself an async function
plus1 = (y) -> Promise.resolve y+1
g = (x) -> x * await plus1 x
# two equivalent ways to test:
g(6).then (v) -> v is 42
do -> assert 42 is await g 6
agent = require 'superagent'
do ->
{text} = await agent.get 'http://stephane.shimaore.net/'
console.log text.length
fs = (require 'fs').promises
{mtime} = await fs.stat '/etc/motd'
- async generator: generator that yields Promises
f = (names) ->
for name in names
{mtime} = await fs.stat name
yield [name,mtime]
return
do ->
for await mtime from f(['/etc/motd','/etc/passwd'])
console.log mtime
# →
# [ '/etc/motd', 2018-01-13T23:36:34.000Z ]
# [ '/etc/passwd', 2019-09-09T17:41:15.752Z ]
- example: transform an API with pagination into a continuous stream of documents
findAsyncIterable = (params,limit = 10) ->
until done # iterate until we retrieve all data
body = null
until body? # iterate until we get a valid response
try
{body} = await agent.post buildFindURL(params,limit)
catch error
if error.status is 404 # invalid query
body = docs: []
else
await sleep 100
{docs} = body
for doc from docs
yield doc
done = docs.length < limit
return
do ->
asyncQuery = findAsyncIterable selector: account: 'bob'
for await v from asyncQuery
console.log v
- before: Node.js
Stream Transform
(e.g.: filter function)
class objectFilterTransform extends Stream.Transform
constructor: (options,filter) ->
options.objectMode = true
super options
@filter = filter
_transform: (obj,dummy,next) ->
if await @filter(obj)
@push obj
next()
return
- after (assuming
S
is an async iterable)
verifier = (filter) -> (S) ->
for await obj from S
if await filter(obj)
yield obj
return
fs = require 'fs'
do ->
content = ''
for await chunk from fs.createReadStream 'file.json', encoding:'utf8'
content += chunk
console.log JSON.parse content
Stream = require 'stream'
Yes = ->
loop
yield 'yes\n'
return
Stream.Readable
.from Yes()
.pipe process.stdout
(blabla startup, S.js, JSX, JSX in CS2)
await
→ exécution synchrone (avant) vs asynchronedo
(toe
) → keep track of rejected Promises