Created
July 4, 2018 06:12
-
-
Save Macil/7a95083723a7b82a4f0b6bb4edcccfaf to your computer and use it in GitHub Desktop.
An example of using Kefir streams with a recursive function.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
'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