Particular case of an asynchronous execution, where the process waits for every single thing,
even if independent.
It's not magic.
let ee = new EventEmitter();
ee.on('data', ({prop}) => {
// ... do something with `prop`
});fs.readFile('path/to/file.ext', (err, data) => {
// ... `err` not null means something went wrong
// ... otherwise consider `data`
});async provides a complete set of utilities for handling callbacks APIs
let promisify = (f) => (...args) => new Promise((resolve, reject) => {
args.length = f.length - 1;
f(...args, (err, data) => {
err ? reject(err) : resolve(data);
});
});
let readFile = promisify(fs.readFile);
readFile('path/to/file')
.then(
(data) => {
// ... do something with `data`
},
(err) => {
// ... do something with `err`
}
);// readable stream
let r = fs.createReadStream('file.txt');
// writable stream
let w = fs.createWriteStream('file.txt.gz');
// duplex stream
let z = zlib.createGzip();
r.pipe(z).pipe(w);import {Transform} from 'stream';
class OddUpper extends Transform {
_transform(chunk, enc, cb) {
for (let i = 0, length = chunk.length; i < length; i += 2) {
chunk.writeUInt8(chunk.readUInt8(i) - 32, i); // uppercase
}
this.push(chunk);
cb();
}
}
var oddUpper = new OddUpper();
oddUpper.pipe(process.stdout);
oddUpper.write('hello world\n');
oddUpper.write('another line');
oddUpper.end();
// output:
// HeLlO WoRlD
// AnOtHeR LiNe
let observable = Rx.Observable.create((observer) => {
observer.next(1);
observer.next(2);
observer.next(3);
setTimeout(() => {
observer.next(4);
observer.complete();
}, 1000);
});
observable.subscribe({
next: (x) => { /* ... work with `x` */ },
error: (err) => { /* ... work with the error `err` */ },
complete: () => { /* ... it has finished */ }
});Rx.Observable.fromEvent(input, 'input')
.map(({target: { value }}) => value) // extract the value
.filter(({length}) => length > 2) // filter by length
.debounceTime(400) // debounce
.distinctUntilChanged() // produce only on change
.switchMap(asyncSearch) // switch producer on each consumption
.subscribe(
(results) => {
// ... work with `results`
},
(err) => {
// ... handle `err`
}
)
;// `yield` and `return` in a generator create the single async I/O
// sequence between the iterator and the wrapper
let getMergedData = co.wrap(function* (...urls) {
let data;
try {
// fetch in parallel
data = yield urls.map(asyncFetch);
} catch(err) {
// ... handle `err`
}
return asyncDataMerge(...data);
});
getMergedData(url1, url2, url3).then((mergedData) => {
// ... work with `mergedData`
});
let sequentialFetch = function* (...urls) {
let url;
while (url = urls.pop()) {
yield asyncFetch(url);
}
};
let getMergedData = co.wrap(function* (...urls) {
let data;
try {
// delegate to a waterfall fetcher
data = yield* sequentialFetch(urls);
} catch(err) {
// ... handle `err`
}
return asyncDataMerge(...data);
});
getMergedData(url1, url2, url3).then((mergedData) => {
// ... work with `mergedData`
});// you get less control than with generators
// but it will eventually not depend on external lib
let getMergedData = async function(...urls) {
let data;
try {
// fetch in parallel
data = await* urls.map(asyncFetch);
} catch(err) {
// ... handle `err`
}
return await asyncDataMerge(...data);
});
getMergedData(url1, url2, url3).then((mergedData) => {
// ... work with `mergedData`
});
function* player(name, table) {
while (true) {
var ball = yield csp.take(table);
if (ball === csp.CLOSED) {
console.log(name + ": table's gone");
return;
}
ball.hits += 1;
console.log(name + " " + ball.hits);
yield csp.timeout(100);
yield csp.put(table, ball);
}
}
// goroutine power but in the same thread
csp.go(function* () {
var table = csp.chan();
csp.go(player, ["ping", table]);
csp.go(player, ["pong", table]);
yield csp.put(table, {hits: 0});
yield csp.timeout(1000);
table.close();
});