Skip to content

Instantly share code, notes, and snippets.

@trxcllnt
Last active July 14, 2016 02:10
Show Gist options
  • Save trxcllnt/144c503bf2bca662ad15fbb887324c95 to your computer and use it in GitHub Desktop.
Save trxcllnt/144c503bf2bca662ad15fbb887324c95 to your computer and use it in GitHub Desktop.
esnextbin sketch
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>ESNextbin Sketch</title>
<!-- put additional styles and scripts here -->
</head>
<body>
<!-- put markup and other contents here -->
</body>
</html>
import { Observable, ReplaySubject } from 'rxjs';
const startTime = Date.now();
const expireTime = 5 /*seconds*/;
const expireError = 'expire-cache';
const root = getRootDiv();
const info = root.appendChild(document.createElement('ul'));
const btns = root.appendChild(document.createElement('div'));
const span = root.appendChild(document.createElement('p'));
const paul = btns.appendChild(getButton('paul'));
const john = btns.appendChild(getButton('john'));
info.style.height = '100%';
info.style.float = 'right';
info.style.margin = '0px';
info.style.padding = '0px';
info.style.overflow = 'overlay';
info.style.listStyleType = 'none';
const peopleCache = {};
const loadPersonByName = loadPerson(peopleCache);
const expirePeopleAfterTimeout = expirePeople(peopleCache);
Observable.merge(
Observable.fromEvent(paul, 'click'),
Observable.fromEvent(john, 'click')
)
.map(({ target }) => target.textContent)
.let(expirePeopleAfterTimeout)
.distinctUntilChanged()
.switchMap(loadPersonByName)
.subscribe((person) => {
span.textContent = `you clicked on ${person}`;
});
function expirePeople(cache) {
return function expirePeopleAfterTimeout(people) {
return people.groupBy((person) => person,
(person) => person,
(person) => person
.timeoutWith(expireTime * 1000, Observable.defer(() => {
delete cache[person.key];
log(`expired ${person.key}`);
return Observable.empty();
}))
.do(() => log(`reset ${person.key} timeout`))
.ignoreElements()
)
.mergeAll();
};
}
function loadPerson (cache) {
return function loadPersonByName (person) {
// Do it this way if you want to allow `switchMap` to
// cancel the pending ajax call if the user clicks a
// different name.
return cache[person] != null ?
cache[person] : (
cache[person] = Observable
// .ajax.get(`people/${person}`)
.defer(() => {
log(`loading ${person}`);
return Observable.of(person).delay(1000);
})
.do(() => log(`loaded ${person}`))
.multicast(new ReplaySubject(1))
.refCount()
);
/*
// You can do it this way if you want the ajax call to
// stay pending once its made. Normally connecting a
// ConnectableObservable would leak memory, but it
// doesn't in this case since we remove each person
// from the cache on timeout
if (cache[person] != null) {
return cache[person];
}
const loadPerson = Observable
// .ajax.get(`people/${person}`)
.defer(() => {
log(`loading ${person}`);
return Observable.of(person).delay(1000);
})
.do(() => log(`loaded ${person}`))
.multicast(new ReplaySubject(1));
loadPerson.connect();
return cache[person] = loadPerson;
*/
};
}
function log (message) {
info.appendChild(document.createElement('li'))
.textContent = `@${Math.round((Date.now() - startTime) / 1000)}s: ${message}`;
}
function getRootDiv(root) {
root = (
document.getElementById('app') ||
document.body.appendChild((
root = document.createElement('div')) && (
root.id = 'app') && (
root)
)
);
root.style.top = 0;
root.style.left = 0;
root.style.right = 0;
root.style.bottom = 0;
root.style.padding = '10px';
root.style.overflow = 'hidden';
root.style.position = 'absolute';
root.style['transform-style'] = 'preserve-3d';
return root;
}
function getButton(name) {
const button = document.createElement('button');
button.textContent = name;
button.style.margin = `5px 5px`;
button.style.padding = `5px`;
return button;
}
{
"name": "esnextbin-sketch",
"version": "0.0.0",
"dependencies": {
"rxjs": "5.0.0-beta.9"
}
}
'use strict';
var _rxjs = require('rxjs');
var startTime = Date.now();
var expireTime = 5 /*seconds*/;
var expireError = 'expire-cache';
var root = getRootDiv();
var info = root.appendChild(document.createElement('ul'));
var btns = root.appendChild(document.createElement('div'));
var span = root.appendChild(document.createElement('p'));
var paul = btns.appendChild(getButton('paul'));
var john = btns.appendChild(getButton('john'));
info.style.height = '100%';
info.style.float = 'right';
info.style.margin = '0px';
info.style.padding = '0px';
info.style.overflow = 'overlay';
info.style.listStyleType = 'none';
var peopleCache = {};
var loadPersonByName = loadPerson(peopleCache);
var expirePeopleAfterTimeout = expirePeople(peopleCache);
_rxjs.Observable
// .ajax.get(`people/${person}`)
.merge(_rxjs.Observable.fromEvent(paul, 'click'), _rxjs.Observable.fromEvent(john, 'click')).map(function (_ref) {
var target = _ref.target;
return target.textContent;
}).let(expirePeopleAfterTimeout).distinctUntilChanged().switchMap(loadPersonByName).subscribe(function (person) {
span.textContent = 'you clicked on ' + person;
});
function expirePeople(cache) {
return function expirePeopleAfterTimeout(people) {
return people.groupBy(function (person) {
return person;
}, function (person) {
return person;
}, function (person) {
return person.timeoutWith(expireTime * 1000, _rxjs.Observable.defer(function () {
delete cache[person.key];
log('expired ' + person.key);
return _rxjs.Observable.empty();
})).do(function () {
return log('reset ' + person.key + ' timeout');
}).ignoreElements();
}).mergeAll();
};
}
function loadPerson(cache) {
return function loadPersonByName(person) {
// Do it this way if you want to allow `switchMap` to
// cancel the pending ajax call if the user clicks a
// different name.
return cache[person] != null ? cache[person] : cache[person] = _rxjs.Observable.defer(function () {
log('loading ' + person);
return _rxjs.Observable.of(person).delay(1000);
}).do(function () {
return log('loaded ' + person);
}).multicast(new _rxjs.ReplaySubject(1)).refCount();
/*
// You can do it this way if you want the ajax call to
// stay pending once its made. Normally connecting a
// ConnectableObservable would leak memory, but it
// doesn't in this case since we remove each person
// from the cache on timeout
if (cache[person] != null) {
return cache[person];
}
const loadPerson = Observable
// .ajax.get(`people/${person}`)
.defer(() => {
log(`loading ${person}`);
return Observable.of(person).delay(1000);
})
.do(() => log(`loaded ${person}`))
.multicast(new ReplaySubject(1));
loadPerson.connect();
return cache[person] = loadPerson;
*/
};
}
function log(message) {
info.appendChild(document.createElement('li')).textContent = '@' + Math.round((Date.now() - startTime) / 1000) + 's: ' + message;
}
function getRootDiv(root) {
root = document.getElementById('app') || document.body.appendChild((root = document.createElement('div')) && (root.id = 'app') && root);
root.style.top = 0;
root.style.left = 0;
root.style.right = 0;
root.style.bottom = 0;
root.style.padding = '10px';
root.style.overflow = 'hidden';
root.style.position = 'absolute';
root.style['transform-style'] = 'preserve-3d';
return root;
}
function getButton(name) {
var button = document.createElement('button');
button.textContent = name;
button.style.margin = '5px 5px';
button.style.padding = '5px';
return button;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment