Skip to content

Instantly share code, notes, and snippets.

@Macil
Created July 4, 2018 06:12
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Macil/7a95083723a7b82a4f0b6bb4edcccfaf to your computer and use it in GitHub Desktop.
Save Macil/7a95083723a7b82a4f0b6bb4edcccfaf to your computer and use it in GitHub Desktop.
An example of using Kefir streams with a recursive function.
'use strict';
const Kefir = require('kefir');
// fetch takes a url string, pretends to fetch it over the network, and returns
// a Kefir stream that emits a Page object when it's done, and then the stream
// ends.
function fetch(url) {
let links;
switch (url) {
case 'foo.com': links = ['bar.com', 'baz.com']; break;
case 'bar.com': links = ['zz.com', 'zzz.com']; break;
case 'baz.com': links = ['foo.com', 'z.com']; break;
case 'z.com': links = ['zz.com']; break;
default: links = [];
}
const page = {url, links};
return Kefir.later(10, page);
}
// getLinks takes a Page object, pretends to spend time parsing it, and returns
// a Kefir stream of all of the links in the page as strings, and then the
// stream ends when the page is done being parsed for links.
function getLinks(page) {
return Kefir.sequentially(1000, page.links);
}
// fetchRecursively takes a url string and returns a Kefir stream of Page
// objects (the same kind fetch returns). fetchRecursively fetches the given
// url, emits the Page object received into the returned stream, gets the links
// from the page object, and repeats the process for all link urls found, but
// skips urls that have already been fetched. The returned stream ends when all
// of the fetching is done.
function fetchRecursively(url, alreadyFetchedUrls = new Set()) {
if (alreadyFetchedUrls.has(url)) return Kefir.never();
alreadyFetchedUrls.add(url);
const pageStream = fetch(url);
return Kefir.merge([
pageStream,
pageStream
.flatMap(getLinks)
.flatMap(url => fetchRecursively(url, alreadyFetchedUrls)),
]);
}
fetchRecursively('foo.com').log('fetchRecursively');
// fetchRecursively <value> { url: 'foo.com', links: [ 'bar.com', 'baz.com' ] }
// fetchRecursively <value> { url: 'bar.com', links: [ 'zz.com', 'zzz.com' ] }
// fetchRecursively <value> { url: 'baz.com', links: [ 'foo.com', 'z.com' ] }
// fetchRecursively <value> { url: 'zz.com', links: [] }
// fetchRecursively <value> { url: 'zzz.com', links: [] }
// fetchRecursively <value> { url: 'z.com', links: [ 'zz.com' ] }
// fetchRecursively <end>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment