Created
March 15, 2019 11:19
-
-
Save trescenzi/b98666294e473ddddfe086a6cdb20799 to your computer and use it in GitHub Desktop.
Rough sketch of a directed graph router.
This file contains 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
class GraphRouter { | |
constructor(state) { | |
this.vertices = {}; | |
this.sortedVerticies = []; | |
this.visitedVerticies = []; | |
} | |
addNode(path, dependencies, resolve) { | |
const vertex = { | |
name: path.split('/').pop(), | |
path, | |
edges: dependencies, | |
resolve, | |
}; | |
this.vertices[path] = vertex; | |
} | |
_visitForSort(vertex) { | |
if (this.visitedVerticies[vertex.path] === 2) return; | |
if (this.visitedVerticies[vertex.path] === 1) throw new Error(`CYCLE FOUND AT ${vertex}`); | |
this.visitedVerticies[vertex.path] = 1; | |
vertex.edges.length && vertex.edges.map((v) => this._visitForSort(this.vertices[v])); | |
this.visitedVerticies[vertex.path] = 2; | |
this.sortedVerticies.push(vertex); | |
} | |
sort() { | |
// Reverse topological sort | |
this.sortedVerticies = []; | |
this.visitedVerticies = []; | |
const vertices = Object.values(this.vertices); | |
while (vertices.length > 0) { | |
this._visitForSort(vertices.shift()); | |
} | |
} | |
_sortIfNotSorted() { | |
if (Object.keys(this.vertices).length > this.sortedVerticies.length) { | |
this.sort(); | |
} | |
} | |
get order() { | |
this._sortIfNotSorted(); | |
return this.sortedVerticies; | |
} | |
next() { | |
this._sortIfNotSorted(); | |
} | |
goTo(route) { | |
this._sortIfNotSorted(); | |
const verticies = this.sortedVerticies; | |
let curr = verticies.shift(); | |
while (curr.path !== route) { | |
console.log('Visiting', curr.path); | |
curr.resolve('some render root', {internet: true}, () => {}); | |
curr = verticies.shift(); | |
} | |
console.log('Visiting', curr.path); | |
curr.resolve('some render root', {internet: true}, () => {}); | |
} | |
_findRouteIndex(route) { | |
this._sortIfNotSorted(); | |
return this.sortedVerticies.findIndex(route); | |
} | |
} | |
const router = new GraphRouter(); | |
const internetDeps = []; | |
const tvDeps = ['/tv-internet/internet']; | |
const phoneDeps = ['/tv-internet/tv']; | |
const tvInterenetDeps = | |
['/tv-internet/internet', '/tv-internet/tv', '/tv-internet/phone', '/sign-up']; | |
const doneDeps = ['/tv-internet', '/promotions', '/sign-up']; | |
const resolveNow = (_, __, resolve) => resolve(true); | |
router.addNode('/tv-internet/internet', internetDeps, (div, state, resolve) => { | |
if (state.internet) { | |
return resolve(); | |
} else { | |
div.innerHTML = `<div> internet </div>` | |
} | |
}); | |
router.addNode('/tv-internet/tv', tvDeps, resolveNow); | |
router.addNode('/tv-internet/phone', phoneDeps, resolveNow); | |
router.addNode('/tv-internet', tvInterenetDeps, resolveNow); | |
router.addNode('/promotions', ['/sign-up'], resolveNow); | |
router.addNode('/sign-up', [], resolveNow); | |
router.addNode('/done', doneDeps, resolveNow) | |
console.log(router.order.map((v) => v.path)); | |
router.goTo('/promotions'); | |
/* | |
[ '/tv-internet/internet', | |
'/tv-internet/tv', | |
'/tv-internet/phone', | |
'/sign-up', | |
'/tv-internet', | |
'/promotions', | |
'/done' ] | |
Visiting /tv-internet/internet | |
Visiting /tv-internet/tv | |
Visiting /tv-internet/phone | |
Visiting /sign-up | |
Visiting /tv-internet | |
Visiting /promotions | |
*/ | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment