Skip to content

Instantly share code, notes, and snippets.

@jooyunghan
Last active January 24, 2018 02:17
Show Gist options
  • Save jooyunghan/8ed381c0a74def1e5e00236375167d0f to your computer and use it in GitHub Desktop.
Save jooyunghan/8ed381c0a74def1e5e00236375167d0f to your computer and use it in GitHub Desktop.
Fetch/Batch
// Blog example
const getPostIds = () => dataFetch({ type: 'FetchPosts' });
const getPostInfo = id => dataFetch({ type: 'FetchPostInfo', id });
function* blog() {
let [ids, x] = yield [getPostIds(), getPostIds()];
return yield ids.map(id => getPostInfo(id));
}
function process(requests) {
requests.forEach(({ request, box }) => {
if (request.type === 'FetchPosts') {
box.push([1, 2, 3]);
} else if (request.type === 'FetchPostInfo') {
box.push({
id: request.id,
date: new Date(),
topic: 'topic' + request.id
});
} else {
console.log('process', request);
}
});
return Promise.resolve();
}
runFetch(blog, process).then(console.log);
// Fetch API
function* dataFetch(request) {
let box = [];
let br = { request, box };
yield Blocked([br]);
return box[0];
}
function runFetch(g, fetch) {
function step(stack, result) {
while (stack.length > 0) {
const i = stack.pop();
const { value, done } = i.next(result);
if (done) {
result = value;
} else if (typeof value.next === 'function') {
stack.push(i);
stack.push(value);
} else if (value instanceof Blocked) {
stack.push(i);
return {
blocked: value.requests,
next: () => step(stack)
};
} else if (value instanceof Array) {
stack.push(i);
let result2 = [];
for (const v of value) {
result2.push(step([v]));
}
if (result2.every(r => 'done' in r)) {
result = result2.map(r => r.done);
} else {
return {
blocked: result2
.filter(r => 'blocked' in r)
.reduce((a, r) => a.concat(r.blocked), []),
next: function next() {
for (let i in result2) {
if ('blocked' in result2[i]) {
result2[i] = result2[i].next();
}
}
if (result2.every(r => 'done' in r)) {
return step(stack, result2.map(r => r.done));
} else {
return {
blocked: result2
.filter(r => 'blocked' in r)
.reduce((a, r) => a.concat(r.blocked), []),
next: next
};
}
}
};
}
}
}
return {
done: result
};
}
let round = 1;
function go(cont) {
const r = cont();
if ('done' in r) {
return Promise.resolve(r.done);
} else {
console.log(`============ ROUND #${round++} ============`);
r.blocked.forEach(((req, i) => console.log(i, req.request)))
return fetch(r.blocked).then(() => go(r.next));
}
}
return go(() => step([g()]));
}
function Blocked(requests) {
return Object.assign(Object.create(Blocked.prototype), { requests });
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment