DEV Community

loading...
Cover image for Snow Days and Javascript Promises

Snow Days and Javascript Promises

Quinn Lashinsky
Front End Developer. Huge fan of Nintendo, baseball, cats, and fitness.
・5 min read

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!

let snowPromise = new Promise((resolve, reject) => {
  // Our Promise function
});
Enter fullscreen mode Exit fullscreen mode

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!

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>}
Enter fullscreen mode Exit fullscreen mode

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.

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"
Enter fullscreen mode Exit fullscreen mode

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.

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
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"
Enter fullscreen mode Exit fullscreen mode

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.
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 ⛄️🤞🏽"
Enter fullscreen mode Exit fullscreen mode

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

So for example:

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

console.log('2')

// 2
// 1
Enter fullscreen mode Exit fullscreen mode
  • If you want access to a result in multiple chained .then() methods, you must return the result from each .then()

No Return -

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

// "1 - Resolve Function"
// "2 - undefined"
Enter fullscreen mode Exit fullscreen mode

Return -

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

// "1 - Resolve Function"
Enter fullscreen mode Exit fullscreen mode

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

Discussion (1)