Skip to content

Instantly share code, notes, and snippets.

View ccnokes's full-sized avatar

Cameron Nokes ccnokes

View GitHub Profile
@ccnokes
ccnokes / AbortController.ts
Last active March 24, 2020 20:46
Minimal AbortController implementation for node.js that doesn't have to shim DOM stuff
import { EventEmitter } from 'events';
class AbortSignal {
private events = new EventEmitter();
constructor(
private getIsAborted: () => boolean
) {}
get aborted(): boolean {
@ccnokes
ccnokes / ObservableMap.ts
Last active November 5, 2019 04:58
A Map class with built-in event emitter that emits a `update` event whenever something changes
class ObservableMap<K, V> extends Map<K, V> {
readonly events = new EventEmitter();
set(key: K, value: V) {
let previousValue = this.get(key);
super.set(key, value);
this.events.emit("update", {
key,
action: "set",
previousValue,
currentValue: this.get(key)
@ccnokes
ccnokes / Batch.ts
Last active October 2, 2019 21:19
A class that manages the logic of batching items together within a timeframe and then passing those items to a function. Sandbox: https://codesandbox.io/s/v86lv7k89l
class Deferred<Type> {
promise: Promise<Type>;
// TODO type these
resolve: any;
reject: any;
then: any;
catch: any;
constructor() {
this.promise = new Promise((resolve, reject) => {
@ccnokes
ccnokes / idObj.ts
Last active August 22, 2019 19:35
Sometimes in React you need a unique `key` to represent an object's identity. Instead of generating an id when you fetch it from an API or generating an id on the fly or using indexes (both will lead to bugs), you can use this which gives you a stable, unique id for an object. Demo: https://codesandbox.io/s/nice-gauss-h424o. Demo with React: htt…
let map = new WeakMap(); // weakly holds all object refs (works in IE11+)
let n = 0; // global counter for ids
export function idObj(obj: any) {
if (map.has(obj)) {
return map.get(obj);
} else {
let key = String(++n);
map.set(obj, key);
return key;
@ccnokes
ccnokes / rafScheduler.ts
Created June 18, 2019 19:59
requestAnimationFrame scheduler
/**
* A function for batching RAFs together
*/
export default function RAFScheduler() {
let queue = [];
let rafId;
let scheduled = false;
const DURATION = 10;
return function scheduleRaf(cb: () => void) {
@ccnokes
ccnokes / never_gonna_give_you_up.sh
Created August 13, 2018 14:43
Plays Rick Astley's "Never Gonna Give You Up" in Spotify
#!/bin/bash
osascript <<EOD
tell application "Spotify"
activate
play track "spotify:track:4uLU6hMCjMI75M1A2tKUQC"
play
end tell
EOD
@ccnokes
ccnokes / set-wallpaper-to-apod.sh
Last active May 18, 2019 17:08
Set your wallpaper to the current Astronomy Picture of the Day (APOD)
# get the URL of the current Astronomy Picture of the Day (APOD)
apod_url=$(curl -s https://api.nasa.gov/planetary/apod?api_key=DEMO_KEY | jq -r '.hdurl')
# get just the image name from the URL
filepath=$(basename "$apod_url")
# Now get the image and save it
curl -s -o "$filepath" "$apod_url"
# Use AppleScript to set it as the wallpaper
@ccnokes
ccnokes / stash_to_patch.sh
Created March 28, 2019 17:47
Convert all stashes to patches in a git repository
#!/bin/bash
stash_count=$(git stash list | wc -l)
i=0
while [[ $i -lt $stash_count ]]; do
git stash show -p stash@{$i} > "stash-$i.patch"
i=$(( $i + 1 ))
done
// This works in the either the main or renderer processes.
const { requireTaskPool } = require('electron-remote');
const work = requireTaskPool(require.resolve('./work'));
console.log('start work');
// `work` will get executed concurrently in separate processes
work().then(result => {
@ccnokes
ccnokes / RICScheduler.ts
Last active February 23, 2019 22:14
RequestIdleCallback scheduler. Create an instance and use it globally to ensure that tasks are efficiently run in as few requestIdleCallbacks as possible (as described here https://developers.google.com/web/updates/2015/08/using-requestidlecallback). Sandbox: https://codesandbox.io/s/r45rv9lv1o
class RICScheduler {
private queue: { task: () => void, id: number }[] = [];
private running = false;
private nextId = 0;
private ricId;
private id() {
return this.nextId++;
}