Last active
March 16, 2023 16:31
-
-
Save danielscottjames/ac19596cbca67dec4280d655c74059c7 to your computer and use it in GitHub Desktop.
TypeScript Async Code Examples
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
//@ts-check | |
/* #region Schedule a new task */ | |
setTimeout(() => { | |
console.log("In Timeout"); | |
}, 100); | |
console.log("After setTimeout"); | |
/* #endregion */ | |
/* #region No Preemption */ | |
setTimeout(() => { | |
console.log("In Timeout"); | |
}, 100); | |
const now = Date.now(); | |
while (Date.now() - now < 5000); // Loop for 10 seconds | |
console.log("After setTimeout"); | |
// Try this, run an infinite loop in a browser tab | |
/* #endregion */ | |
/* #region Other source of async tasks */ | |
const fs = require('fs'); | |
// Other common sources: file system, network requests, Mouse/Keyboard events, requestAnimationFrame, etc... | |
fs.readFile('hello.txt', (err, result) => { | |
if (err) { | |
console.log(err); | |
} else { | |
console.log(result.toString()); | |
} | |
}); | |
setTimeout(() => console.log("In timeout"), 20); | |
console.log("After readFile"); | |
// Question?: What order to the log statements execute in? | |
/* #endregion */ | |
/* #region What is a Promise? */ | |
// Encapsulates the state for a callback | |
const promise = new Promise((resolve, reject) => { | |
// call resolve to trigger any .then's | |
// call reject to "throw an error" and trigger .catch's | |
// Do some async task, like a network request, file system access, etc... | |
setTimeout(() => { | |
try { | |
resolve(2); | |
} catch (error) { | |
reject(error); | |
} | |
}, 1); | |
}); | |
// Use .then to schedule a callback for when this promise resolves | |
promise.then(r => console.log(r)); // => 2 | |
// Calling .then creates a new promise, can be chained like `.map` on other data structures | |
const newPromise = promise.then(r => r * 2); | |
// Notice that the resolve value of the first promise never changes | |
promise.then(r => console.log(r)); // => 2 | |
newPromise.then(r => console.log(r)); // => 4 | |
/* #endregion */ | |
/* #region Rewriting FS example with a promise */ | |
const fs = require('fs'); | |
const fileContents = new Promise((resolve, reject) => { | |
fs.readFile('hello.txt', (err, result) => { | |
if (err) { | |
reject(err); | |
} else { | |
resolve(result.toString()); | |
} | |
}); | |
}); | |
fileContents.then(result => { | |
console.log(result); | |
}); | |
/* #endregion */ | |
/* #region Implementing your own Promise */ | |
class MyPromise { | |
_resolved = undefined; | |
_resolve = (value) => { | |
if (!this._resolved) { | |
this._resolved = value; | |
this.thens.forEach(fn => fn(this._resolved)); | |
} | |
} | |
thens = []; | |
then(fn) { | |
let _resolve; | |
const newMyPromise = new MyPromise(resolve => { | |
_resolve = resolve; | |
}); | |
let wrappedFn = () => { | |
_resolve(fn(this._resolved)); | |
} | |
if (!this._resolved) { | |
this.thens.push(wrappedFn); | |
} else { | |
wrappedFn(); | |
} | |
return newMyPromise; | |
} | |
constructor(init) { | |
init(this._resolve/* TODO: make these rejectable */); | |
} | |
} | |
const promise = new MyPromise((resolve, reject) => { | |
// call resolve to trigger any .then's | |
// call reject to "throw and error" and trigger .catch's | |
// Do some async task, like a network request, file system access, etc... | |
setTimeout(() => { | |
try { | |
resolve(2); | |
} catch (error) { | |
reject(error); | |
} | |
}, 1); | |
}); | |
promise.then(r => console.log(r)); // => 2 | |
const newPromise = promise.then(r => r * 2); | |
promise.then(r => console.log(r)); // => 2 | |
newPromise.then(r => console.log(r)); // => 4 | |
/* #endregion */ | |
/* #region Question 1 - Promises */ | |
// Which order do they log? | |
setTimeout(() => console.log("#5"), 0); | |
const myPromise = new Promise((resolve) => { | |
console.log("#1: In Promise constructor callback.") | |
resolve(42); | |
}); | |
console.log("#2: Before myPromise.then"); | |
myPromise.then((result) => console.log(`#3: Promise result: ${result}`)); | |
console.log("#4: After myPromise.then"); | |
/* #endregion */ | |
/* #region Question 2 */ | |
// Which order do they log? | |
Promise.resolve(17).then((result) => console.log(`#1: Promise result: ${result}`)); | |
console.log("#2: After myPromise.then"); | |
/* #endregion */ | |
/* #region promisify */ | |
// Callbacks suck, so they invented promisify (only in Node) | |
const util = require('util'); | |
const fs = require('fs'); | |
var promisify = util.promisify; | |
var readFile = promisify(fs.readFile); | |
const promiseResult = readFile('./hello.txt'); | |
promiseResult | |
.then((result) => console.log(result.toString())) | |
.catch(e => { | |
console.log(e); | |
}); | |
/* #endregion */ | |
/* #region async/await */ | |
// Promises suck so they invented async/await | |
const util = require('util'); | |
const fs = require('fs'); | |
var promisify = util.promisify; | |
var readFile = promisify(fs.readFile); | |
(async () => { | |
try { | |
const result = await readFile('hello.txt'); | |
console.log(result.toString()); | |
} catch (e) { | |
console.log(e); | |
} | |
})(); | |
// Question?: What is the return value of any async function? | |
/* #endregion */ | |
/* #region Question 4 */ | |
// Which order do they log? | |
(async () => { | |
const promise = Promise.resolve(); | |
promise.then(() => console.log('#1: Promise.then')); | |
console.log('#2: before await'); | |
await promise; | |
console.log('#3: after await'); | |
})(); | |
/* #endregion */ | |
/* #region You don't always have to `await` a promise */ | |
(() => { | |
const unused = sendBeaconEventButIDontCareEnoughToBlockTheActionOfMyButton(); | |
for (const thing of myThings) { | |
await doSomething(thing); | |
} | |
// vs | |
await Promise.all(myThings.map(thing => doSomething(thing))); | |
})(); | |
/* #endregion */ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment