Last active
March 22, 2019 21:07
-
-
Save machuga/e0dae53637be1ed6b3a97923cfadc775 to your computer and use it in GitHub Desktop.
Grokkable Concurrent JavaScript - Teaching Asynchronous Patterns and Refactorings
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
const get = require('./get'); // get(url, callback) | |
const githubApi = 'https://api.github.com'; | |
const githubEventsUrlFor = username => `${githubApi}/users/${username}/events`; | |
const githubRepoUrlFor = repo => `${githubApi}/repos/${repo}`; | |
const fetchReposForLatestActivity = (user, callback) => { | |
let timeout = setTimeout(function() { | |
callback(new Error('Timed out')); | |
}, 3000); | |
get(githubEventsUrlFor(user), (err, allEvents) => { | |
if (err) { | |
return callback(err); | |
} | |
const events = allEvents.slice(0, 3); | |
const repos = []; | |
let remainingCount = events.length; | |
events.forEach(event => { | |
get(githubRepoUrlFor(event.repo.name), (err, data) => { | |
if (err) { | |
return callback(err); | |
} | |
repos.push({ | |
author: data.owner.login, | |
avatar: data.owner.avatar_url, | |
name: data.name, | |
full_name: data.full_name, | |
url: data.html_url, | |
description: data.description | |
}); | |
remainingCount -= 1; | |
if (remainingCount <= 0) { | |
clearTimeout(timeout); | |
callback(null, repos) | |
} | |
}); | |
}); | |
}); | |
}; | |
fetchReposForLatestActivity('machuga', (err, repos) => { | |
if (err) { | |
console.error(err); | |
return; | |
} | |
console.log(repos); | |
}); |
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
const get = require('./get'); // get(url, callback) | |
const githubApi = 'https://api.github.com'; | |
const githubEventsUrlFor = username => `${githubApi}/users/${username}/events`; | |
const githubRepoUrlFor = repo => `${githubApi}/repos/${repo}`; | |
const fetchRepo = (repoName, callback) => { | |
get(githubRepoUrlFor(repoName), callback); | |
}; | |
const fetchEventsForUser = (user, callback) => { | |
get(githubEventsUrlFor(user), callback); | |
}; | |
const fetchReposForEvents = (events, callback) => { | |
const repos = []; | |
let remainingCount = events.length; | |
events.forEach(event => { | |
fetchRepo(event.repo.name, (err, data) => { | |
if (err) { | |
return callback(err); | |
} | |
repos.push({ | |
author: data.owner.login, | |
avatar: data.owner.avatar_url, | |
name: data.name, | |
full_name: data.full_name, | |
url: data.html_url, | |
description: data.description | |
}); | |
remainingCount -= 1; | |
if (remainingCount <= 0) { | |
callback(null, repos) | |
} | |
}); | |
}); | |
}; | |
const fetchReposForLatestActivity = (user, callback) => { | |
let timeout = setTimeout(function() { | |
callback(new Error('Timed out')); | |
}, 3000); | |
fetchEventsForUser(user, (err, allEvents) => { | |
if (err) { | |
return callback(err); | |
} | |
fetchReposForEvents(allEvents.slice(0, 3), (err, repos) => { | |
if (err) { | |
return callback(err); | |
} | |
clearTimeout(timeout); | |
callback(null, repos); | |
}); | |
}); | |
}; | |
fetchReposForLatestActivity('sgrif', (err, repos) => { | |
if (err) { | |
console.error(err); | |
return; | |
} | |
console.log(repos); | |
}); |
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
const callbacks = [ | |
(done) => { setTimeout(() => { done(null, '1') }, 500) }, | |
(done) => { setTimeout(() => { done(null, '2') }, 200) }, | |
]; | |
const whenAllSettled = (fns, callback) => { | |
const results = []; | |
let remainingCount = fns.length; | |
const done = (i) => (err, result) => { | |
let resultObject; | |
if (err) { | |
resultObject = { type: 'failure', value: err }; | |
} else { | |
resultObject = { type: 'success', value: result }; | |
} | |
results[i] = resultObject; | |
remainingCount -= 1; | |
if (remainingCount <= 0) { | |
callback(null, results); | |
} | |
}; | |
fns.forEach((fn, i) => { | |
fn(done(i)); | |
}); | |
} | |
whenAllSettled(callbacks, (err, results) => { | |
console.log("All done with round 1!", results); | |
whenAllSettled([ | |
(done) => { setTimeout(() => done(new Error('oops')), 500); } | |
], (err, results) => { | |
console.log("All done with round 2!", results); | |
}) | |
}); |
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
console.log("first"); | |
setTimeout(function fifth() { console.log("fifth"); }, 500); | |
setTimeout(function third() { console.log("third"); }, 0); | |
setTimeout(function fourth() { console.log("fourth"); }, 0); | |
console.log("second"); |
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
const startTime = Date.now(); | |
console.log("first at", startTime) | |
announceTick(); | |
setTimeout(createTickLoggerFor("seventh"), 500); | |
setTimeout(createTickLoggerFor("third"), 0); | |
setTimeout(function differentTick() { | |
announceTick(); | |
logWithOffset("fourth"); | |
setTimeout(createTickLoggerFor("sixth"), 0); | |
for (let i = 0; i < 100000; i++) { | |
process.stdout.write(`Delaying: ${i}\r`); | |
} | |
console.log('\n'); | |
logWithOffset("fifth"); | |
setTimeout(createTickLoggerFor("eighth"), 300); | |
}, 0); | |
logWithOffset("second"); | |
function timeFromStart() { | |
return Date.now() - startTime; | |
} | |
function createTickLoggerFor(msg) { | |
return function() { | |
announceTick(); | |
logWithOffset(msg); | |
} | |
} | |
function logWithOffset(msg) { | |
console.log(`[Offset: ${timeFromStart()}]: ${msg}`); | |
} | |
function announceTick() { | |
process.nextTick(() => { | |
console.log("-----TICK-----") | |
}); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Gist will not update
2
file to use 2 spaces or tabs. I am so sorry, internet. I have failed you 😢