Skip to content

Instantly share code, notes, and snippets.

@JustinBeckwith
Created December 28, 2024 23:19
Show Gist options
  • Save JustinBeckwith/dec2c2c7be356609be246e7c34148150 to your computer and use it in GitHub Desktop.
Save JustinBeckwith/dec2c2c7be356609be246e7c34148150 to your computer and use it in GitHub Desktop.
Promises and JavaScript
// I found myself explaining this today, and figured it may be good to post something here for future reference. Enjoy!
/**
* Using callbacks
*
* Callbacks are a fancy way of saying that we pass functions around
* as arguments to other functions. In this case, we expect doStuff to
* take a really long time (a second!). When the second is over, we
* invoke the callback function.
*/
function doStuff(callback) {
// imagine this takes a very long time
setTimeout(() => {
// after a second, invoke the callback function that was passed to us
callback();
}, 1000);
}
console.log('start...');
// we pass a function to doStuff that will be called when done
doStuff(() => {
console.log('done');
// After calling it once, we may choose to call doStuff a second time
doStuff(() => {
console.log('done again');
// As you can see... this works, but it gets unwieldy quickly
doStuff(() => {
console.log('done again again');
});
});
});
/**
* Using promises
*
* Promises are a way to handle asynchronous code in a more readable way.
* A promise is an object that represents the eventual completion (or failure)
* We can return promises, and then call `.then` or `.catch` on them.
*/
function doStuff() {
return new Promise((resolve, reject) => {
// imagine this takes a very long time
setTimeout(() => {
// after the second is up, call `resolve`. This is very similar
// to the callback function in the previous example
resolve();
}, 1000);
});
}
// Notice that the promise is an actual object! We can log it,
// or call functions on it.
const p = doStuff();
console.log(p);
console.log('start...');
// The `then` method is called after `doStuff` is finished
p
.then(() => {
console.log('done');
return doStuff();
})
.then(() => {
// In this example, chaining is a little better that the nested callback example
console.log('done again');
return doStuff();
})
.catch((e) => {
console.error(e);
});
/**
* Using async/await
*
* While promises were a nice improvement over callbacks, they're still
* not quite as easy to use as we'd like. That's where async and await come in!
* These are what we call "syntatic sugar" - they just make dealing
* with promises a little easier.
*/
// instead of creating a new promise object and returning it, we can
// declare our function as "async" - promise creation is done for us
async function doStuff() {
await new Promise((resolve, reject) => {
// imagine this takes a very long time
setTimeout(() => {
resolve();
}, 1000);
});
}
console.log('start...');
// The doStuff function actually still returns a promise!
const p = doStuff();
console.log(p);
// Instead of calling .then on our promise, we can just `await` it.
await p;
console.log('done');
// Chaining is easiest here, because we just keep calling `await`
await doStuff();
console.log('done again');
await doStuff();
console.log('done again again');
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment