JavaScript Promises: Making Sense of the Madness 😤
Tags: beginners, tutorial, javascript, programming
Published: 2023-03-24 15:00:17

Hey there, party people! 🎉 If you've ever found yourself scratching your head over Promises in JavaScript, you're in the right place. I've been seeing a ton of questions about this topic, so today I'm on a mission to clear things up and help you master the art of Promises. Get ready for some fun, laughter, and a little bit of learning as we venture into the wild world of Promises! 😎 🎢
<img width="100%" style="width:100%" src="https://media.giphy.com/media/xRYZdfv3DgIQb1dvNA/giphy.gif">

## What’s a Promise in JavaScript? 🤔
A Promise is a JavaScript object that represents an asynchronous function. It's like your friend telling you they'll buy you a pizza later. You don't know exactly when it's gonna happen, but you trust them to deliver. 🍕
<img width="100%" style="width:100%" src="https://media.giphy.com/media/QhjR3MG9ZFfjB6BtIZ/giphy.gif">

```javascript
// Create a Promise object
let sayHello = new Promise(function (resolve, reject) {

	// In 5 seconds, resolve the Promise.
	// Pass along "Hi, universe!" to any callback methods
	setTimeout(function () {
		resolve('Hi, universe!');
	}, 5000);

});
```

In the example above, `sayHello()` is a Promise that in 5 seconds, something will happen. You can attach functions that should run when the Promise resolves using the `Promise.then()` method.

```javascript
// After 5 seconds, if the Promise resolves,
// this will log "Hi, universe!" into the console
sayHello.then(function (msg) {
	console.log(msg);
});
```

When you create a Promise, you pass in a callback function as an argument.

Inside the function, you define two parameters: `resolve` and `reject`. These are implicit arguments the Promise passes into your callback function.

When the Promise should be considered completed, run the `resolve()` method. You can pass in arguments that should get passed into the `Promise.then()` method callback function into the `resolve()` method.

In the example above, we passed Hi, universe! into `resolve()`. This was passed along to the `Promise.then()` method as the msg argument.

## Rejecting a Promise 🚫

Similarly, you run the `reject()` method if the Promise should be considered failed. This is like your friend promising you that pizza, but then they run out of money. Bummer, dude! 😢
<img width="100%" style="width:100%" src="https://media.giphy.com/media/TY3bikeN6R4DS2wpcN/giphy.gif">

You can pass in any error messages or information about the rejection as arguments. You can run a callback when a Promise fails using the `Promise.catch()` method.

In the next example, let’s modify `sayHello()` to `reject()` before the timeout completes.

```javascript
// Create a Promise object
let sayHello = new Promise(function (resolve, reject) {

	reject('Unable to say hi.');

	// In 5 seconds, resolve the Promise.
	// Pass along "Hi, universe!" to any callback methods
	setTimeout(function () {
		resolve('Hi, universe!');
	}, 5000);

});
```
Now, we can add a `Promise.catch()` method to detect this failure and do something about it. (Like ordering our own pizza! 🍕)

```javascript
// Will warn "Unable to say hi." in the console.
sayHello.then(function (msg) {
	console.log(msg);
}).catch(function (error) {
console.warn(error);
});
```

Because `reject()` runs before `resolve()` does, the `catch()` callback method will run and show the error message that was passed in.

## Chaining 🚂

You can chain multiple `Promise.then()` methods together, and they’ll run in sequence. It's like setting up a domino effect—each one triggers the next. 🎲
<img width="100%" style="width:100%" src="https://media.giphy.com/media/9xctlfYe29DYG5lfhG/giphy.gif">

Whatever you return from the current `Promise.then()` method gets passed along to the next `Promise.then()` method after it in the chain. Let’s create a new Promise called `count`.

It will `resolve()` immediately, and pass along `1` as an argument.

```javascript
// Create a Promise object
let count = new Promise(function (resolve, reject) {
	resolve(1);
});
```

Now, we can chain some **`Promise.then()`** methods together. In each one one, we’ll log **`num`**, increase it by **`1`**, and return it to the next argument in the sequence.

In the first **`Promise.then()`** method, **`num`** is **`1`**. In the second, it’s **`2`**. In the last one, it’s **`3`**.

```jsx

// logs 1, then 2, then 3, to the console
count.then(function (num) {
	console.log(num);
	return num + 1;
}).then(function (num) {
	console.log(num);
	return num + 1;
}).then(function (num) {
	console.log(num);
	return num + 1;
});
```

You can attach `Promise.then()` methods at any time ⏰

One of my favorite things about Promises is that if you assign one to a variable, you can attach **`Promise.then()`** methods on it at any time—even after the Promise has already resolved.

If the Promise hasn’t resolved yet, the callback will run once it does. If it has resolved, the callback will run immediately. It's like a pizza that's already been delivered and is just waiting for you to dig in. 🍕

```jsx
// Create a Promise that resolves immediately
let question = new Promise(function (resolve, reject) {
	resolve(42);
});

// Attach a callback 5 seconds after it's resolved
setTimeout(function () {

	// This will run as soon as the timeout completes, because the Promise has already resolved
	question.then(function (answer) {
		console.log(answer);
	});

}, 5000);
```

Hope that helps a bit, folks! Tomorrow, we’ll look at a practical use of Promises: the **`fetch()`** method. Stay tuned, and don't forget to practice those Promises in the meantime. After all, practice makes perfect...or at least a little less confusing! 😄