Snow Days and Javascript Promises
Tags: javascript, beginners, webdev
Published: 2021-02-10 18:42:05

Your eyes are glued to the TV. You watch the news in awe, just waiting for them to get to the weather forecast. You haven't had a snow day all year, and you're hoping that tomorrow will be the first. You think of all the things you'll be able to do—Drink hot chocolate, watch a movie, sleep in, sled, build a snowman with a bunch of friends. It all sounds so amazing.

Finally, the weather forecast comes on and they are promising snow tomorrow!

```javascript
let snowPromise = new Promise((resolve, reject) => {
  // Our Promise function
});
```

Now all we can do is wait! We don't know whether it will snow or not, and we won't know until tomorrow. We then find out if it snows our school district will announce school closures at 7am tomorrow! It's currently 6pm. We have 13 hours until this prediction proves to be true or false!

You are elated. So happy, you almost miss the forecaster tell you that there's only 30% chance of snow happening. If it snows, school will be closed.

You're gonna be absolutely devastated if it doesn't!

```javascript
function willItSnow() {
  return Math.random() < 0.3;
}

let snowPromise = new Promise((resolve, reject) => {
  setTimeout(() => {
    if (willItSnow()) {
      resolve("School's Closed");
    }
    reject("School's Open");
  }, 46800000); // 13 hours in milliseconds
});

console.log(snowPromise);

// Promise {<pending>}
```

It looks like things are in motion! Our `snowPromise` will act as a placeholder, waiting for an asynchronous operation to complete (in our case a `setTimeout`), resolving or rejecting with data. In our case, 13 hours later.

That's a long time to wait...what're we gonna do between now and our predicted snowfall?

If we didn't use a `Promise` we wouldn't be able to do things like perform our snow-bringing bed time rituals. We would be blocked from doing anything else. We'd just sit on the ground waiting to hear if school is closed or not for 13 HOURS. This sounds like a huge waste of time!

The asynchronous nature of a `Promise` lets us run other code while we wait for our `Promise` to resolve or reject. While this happens, we can go ahead with leaving a spoon under our pillow and flushing ice cubes down the toilet. This will definitely ensure we get snow tomorrow!

It's been an exciting day and we still don't know whether it will or won't snow.

To get ready, we'll turn our PJ's inside out and look forward to our `snowPromise` result in the morning!

# Next Morning

We wake up! We're excited! But we're unsure of whether school is closed or not. We need to hear it from the source. But how do we find our information?! Listening to the radio, tv, or reading information on the internet may help us figure out if school is closed or not. These are conduits for receiving the information, much like `Promise` methods we are going to discuss below!

`Promise`'s have a few methods that will allow us to handle our eventual returned result.

## Promise Methods

We can handle a `Promise` using 3 different types of promise handlers; `.then()`, `.catch()`, `.finally()`

### Then

- `.then(onFulfilled, onRejected)` - This method will let us handle a success and error cases, which are technically called our `onFulfilled` and `onRejected` handlers.

  Both of these parameters must be functions.

```javascript
function willItSnow() {
  return Math.random() < 0.3;
}

let snowPromise = new Promise((resolve, reject) => {
  setTimeout(() => {
    if (willItSnow()) {
      resolve("School's Closed");
    }
    reject("School's Open");
  }, 1000);
  // We'll use 1 second here and going forward so we don't have to wait for
  // 13 hours for our Promise to resolve
});

snowPromise.then(
  // onFulfilled
  (value) => {
    console.log(value);
  },
  // onRejected
  (error) => {
    console.log(error);
  }
);

// If it snows, below will be logged to the console:
// "School's Closed"

// If it doesn't snow, below will be logged to the console:
// "School's Open"
```

If our `snowPromise` `resolve`'s, it will pass any arguments we passed to our `resolve` function to our `onFulfilled` handler function.

If our `snowPromise` `reject`'s, we'll pass any arguments we passed to our `reject` function to our `onRejected` handler function.

Finally, we're able to tell whether school is closed or not!

Put the above code into your chosen Web Browser's console or a program like [RunJS](https://runjs.app/).

Is School Closed?! That's amazing! That means our `Promise` resolved and our `onFulfilled` function ran! Let's go play in the snow!

Is School Open?! That's unfortunate! That means our `Promise` rejected and our `onRejected` function ran. Time to get ready for school...

This may seem a bit cluttered to you though. It may be useful to have both possible paths within our `.then()` handler, but we can also use a different method to handle our `onRejected` function...

### Catch

- `.catch(onRejected)` - This method will let us handle our error case, which is technically called our `onRejected` handler

```javascript
function willItSnow() {
  return Math.random() < 0.3;
}

let snowPromise = new Promise((resolve, reject) => {
  setTimeout(() => {
    if (willItSnow()) {
      resolve("School Closed");
    }
    reject("School Open");
  }, 1000);
});

snowPromise
  // onFulfilled
  .then((value) => console.log(value))
  // onRejected
  .catch((error) => console.log(error));

// If it snows, below will be logged to the console:
// "School's Closed"

// If it doesn't snow, below will be logged to the console:
// "School's Open"
```

This method makes it easier to break apart our success and failure/error states!

---

**_TIP: We can even chain a bunch of `.then()`'s together and add a single `.catch()` at the end to handle any error from our `Promise` or any previous `.then()`_**

---

Lastly, we know we'll always want more snow. Multiple snow days in a row? That sounds like heaven!

### Finally

- `.finally(onFinally)` - This `Promise` method allows us to execute some code whether or not our Promise `resolve`'s or `reject`'s.

```javascript
function willItSnow() {
  return Math.random() < 0.3;
}

let snowPromise = new Promise((resolve, reject) => {
  setTimeout(() => {
    if (willItSnow()) {
      resolve("School Closed");
    }
    reject("School Open");
  }, 1000);
});

snowPromise
  // onFulfilled
  .then((value) => console.log(value))
  // onRejected
  .catch((error) => console.log(error))
  .finally(() => console.log("🤞🏽⛄️ PLEASE SNOW TOMORROW ⛄️🤞🏽"));

// If it snows, below will be logged to the console:
// "School's Closed"
// "🤞🏽⛄️ PLEASE SNOW TOMORROW ⛄️🤞🏽"

// If it doesn't snow, below will be logged to the console:
// "School's Open"
// "🤞🏽⛄️ PLEASE SNOW TOMORROW ⛄️🤞🏽"
```

Well...are you going to school today? Or do you have the day off? Either way, we'll always hope for more snow.

Let's bring this home with some final considerations to remember when using Promises.

### Final Considerations

- **_In Javascript, all asynchronous code will only run if there are no other functions on the [Call Stack](https://blog.usejournal.com/everything-you-need-to-know-about-event-loop-in-javascript-1f14f94e5ab6)_**

So for example:

```javascript
new Promise((resolve, reject) => setTimeout(resolve, 2000)
	.then(() => {
		console.log("1")
	})

console.log('2')

// 2
// 1
```

- **_If you want access to a result in multiple chained `.then()` methods, you must return the result from each `.then()`_**

No Return -

```javascript
new Promise((resolve, reject) => {
  resolve("Resolve Function");
})
  .then((value) => {
    console.log(`1 - ${value}`);
  })
  .then((value) => {
    console.log(`2 - ${value}`);
  });

// "1 - Resolve Function"
// "2 - undefined"
```

Return -

```javascript
new Promise((resolve, reject) => {
  resolve("Resolve Function");
})
  .then((value) => {
    return value;
  })
  .then((value) => {
    console.log(`1 - ${value}`);
  });

// "1 - Resolve Function"
```

❄️ Now let's get back to having a snowball fight! ❄️