Guide to Promises in TypeScript
This guides examines how to work with Promises in TypeScript, including: what promises are, how to create a promise, and how to work with promises.
Guide Tasks
  • Read Tutorial
  • Watch Guide Video
Video locked
This video is viewable to users with a Bottega Bootcamp license

In this guide, I'm going to walk through exactly how we can work with promises in typescript. However, before we can talk about this I want to give more of an explanation on what promises are. Thankfully because of the way promises were created and how it's named It's pretty easy and straightforward to compare it to a real-world scenario and that is a promise in real life.

Real World Example

So imagine that I come to you and I say that I am going to mow your lawn. Now that is a promise that I've made a deal. And there are a couple things that could happen. When I say I'm going to mow your lawn there are three scenarios the first one is that I go outside and I start mowing that scenario 1 and in typescript, we would say that this is the pending status. This is kind of like what happens when we make an API request and it creates a promise or starts a promise and we're waiting to see what is going to happen. Now taking the Mowing example further if I complete the Mowing process I'm going to come back and I'm going to say I'm done. And in that case, I was successful and I fulfilled my promise in typescript we would say that this is been resolved.

The keyword here is resolved. And that means that the promise proved to be true. Came back successful and everything went as planned. However what happens if I run away and I just start running down the street and I do not mow your lawn. That means that I did not complete the mowing process successfully. Now there is a special term for this and this is going to be called the reject status. And what this would be akin to is sending out an API request and having an error message come back either the server was down or any number of various errors. If you want to take this a step further in the analogy isn't that always the case that maybe I lied about moving the lawn that also could be that I went outside to mow the lawn and there was no gas in the lawn mower or the lawn mower is broken or something like that. All kinds of different reasons why I may not be able to hold true to my promise just like there are all kinds of reasons why a program may not be able to fulfill the promise successfully. However, what I really want to kind of impart to you is the three stages of a promise. One is when it's pending the next is when it's successful which is what we'll call resolved. And the last one is when it's rejected.

So those are the three things and I'm going to keep this comment here in the source code just say have access to it. Can that analogy in your mind because when I was learning about promises I heard kind of a similar analogy and that was one of the things that really made it clear to me. Now in order to use promises in the version of typescript, we're using we need to put something at the top of the file and actually at the very top of the file. Just so it's clear that's being used. And this is going to be called use strict. Now what this means is that we're going to be using the strict definition or the strict process in Javascript if you have any experience with javascript and you probably have heard about the strict process or the strict syntax. That's what we're doing here. It doesn't really change how we're going to be building the program. It's simply something that is required for the typescript compiler for this ES6 version.

As a side note if you're keeping your compiler options in your Ts config file if you go back to some of your previous classes or your previous coursework such as the work that we did with classes or some of those things or even anyone that has that the let statement included that is going to now no longer work without put strict at the top so just as a side note if you go and try to rerun any of those programs and you get an error if you're using the new compiler options you just have to put that at the top and you'll be good to go.

So now let's move on forward and let's talk about how we can create a promise. So usually the way promises are created. This is the traditional way is we're going to create an anonymous function or create a function expression. And for example in this guide, I'm going to mimic the process of uploading an image or anything like that to a server and we're going to have a number of processes that we're going to force to happen in a specific order. So I'm going to call this function perform upload and it says We're gonna set it equal to an anonymous function and this function is going to take one parameter. The parameter is are going to be Image status. And that's going to be of type string. Now this is going to return a promise. So this promise is going to be returned. And also we're going to pass a key-value pair inside of this promise, so we're going to inside of it put in angle brackets and inside of that, place image status and set that equal to strength. So what that's going to what we're essentially saying is this program is going to return a promise and this promise is going to contain a status and that is what is going to be returned when perform upload is called.

"use strict";
let performUpload = function(imgStatus : string) : Promise<{imgstatus : string}> {
}

Now the next thing we're going to do is we need to actually return it. So we're going to say return new promise and inside of the promise, we're going to pass a couple things. The first thing we're going to pass is going back to our lawnmower example. We need to pass and what will happen when the item is successful. So we need to pass in a resolve argument. And what this is saying is that when the item is successful we're going to be resolving this process, so this is what's going to happen when that occurs. What I want to do and notice how I'm using our fat arrow syntax for the function here I'm going to console log out something and we're to use string interpellation So the use of tactics and a status and asset status equal to whatever the value of image status is. And right after the curly brackets, I'm going to do another backtick. And in that line of code and because I want to kind of mimic a real-world process I'm going to put a set timeout function in here and with set timeouts this one if you remember back to when we did this in our callback we're going to pass a timeout another function and we're going to use another fat arrow in order to do it. And inside of the fat arrow, we're going to place exactly what we want this to do. So here inside of the set timeout, This is where we're going to pass resolve. Now if you notice resolve is going to work like a function here. So resolve even though you notice that resolve is an argument we're going to pass this argument a function, and we need to pass in the value that we want to return. So it what really is happening here is that when a successful promise has occurred. So there are no issues and everything comes back. What we're saying is that we're going to return the image status. And remember we're returning this as a key-value pair. If part of this still seems a little bit confusing Do not worry we're going to go through and kind of go line by line on exactly what's happening to review here. I want to pause this for one second so I'm going to put in a one thousand millisecond call here. That is it. Except for adding a semicolon at the end of this and that is a promise.

"use strict";
let performUpload = function(imgStatus : string) : Promise<{imgstatus : string}> {
  return new Promise((resolve) => {
    console.log(`Status: ${imgStatus}`);
    setTimeout(() => {
      resolve({ imgStatus: imgStatus });
    }, 1000);
  });
}
}

So it's going to make a little bit more sense everything that's going on here when we actually call the promise. So first thing I'm going to do is create some variables. So say var upload. var compress, and then var transfer. And now that we have all this in place now we can actually call our promise.

var upload;
varcompress;
var transfer;

So our promises called perform upload. And in order to start this, we're going to pass in whatever status we want to do. So, in this case, I'm going to say uploading and then we're going to process the very special keyword then. Now if you've never worked with promises before then you may have never heard of the word then in programming. I like it because it's a very nice and sequential and it's a great way of organizing code because to me it almost reads like English. So the way we're going to do this is starting a new line. You could put all this on the same line. However, that would be very difficult to read. So standard convention is to put on a new line so we call the function then and inside of then and then takes an argument and it takes in a callback. So we're going to pass in the response and then inside of that. We are going to use our fat arrow and we're going to pass in the response and set upload which is the variable that we created right here and we're going to set upload equal to the response. Then I want to return a value in this function and say perform upload.

So we're calling the promise again that now we're going to pass in the value of compressing which is another image status. And let me just copy and paste this code because we're going to use this for each one of the statuses. So we're going to do that one and then we're going to do one more but this last one is the final one so this one is going to be slightly different. So this one is going to say transferring, and we're not going to set upload equal to it. We're going to set compress equal to it. Then the last one is going to transfer this one is going to say image upload completed. At the very end add a semicolon and this should all work. So let me come over here to the terminal. Run the code.

performUpload('uploading...')
.then((res) => {
  upload = res;
  return performUpload('compressing...');
})
.then((res) => {
  upload = res;
  return performUpload('transferring...');
})
.then((res) => {
  upload = res;
  return performUpload('Image upload completed.');
})

Everything looks like it works there. This is node 29_promises in case you're following along with the source code. You can see it uploads compresses transfers and the image upload process has worked. So that worked. However, if you've never worked with promises before this probably didn't make a lot of sense and so I want to circle back and kind of go through each element and can analyze what it's doing. So interview here. This is our actual promise.

"use strict";
let performUpload = function(imgStatus : string) : Promise<{imgstatus : string}> {
  return new Promise((resolve) => {
    console.log(`Status: ${imgStatus}`);
    setTimeout(() => {
      resolve({ imgStatus: imgStatus });
    }, 1000);
  });
}
}

var upload;
varcompress;
var transfer;

performUpload('uploading...')
.then((res) => {
  upload = res;
  return performUpload('compressing...');
})
.then((res) => {
  upload = res;
  return performUpload('transferring...');
})
.then((res) => {
  upload = res;
  return performUpload('Image upload completed.');
})

So our promise is called perform upload and our promise is an anonymous function. It takes an image status which has a string value and then it is going to expect that we're going to return a promise because we said that we're going to expect to return this. That's why the first thing we do is we say return a new promise. So this means that when this function is called It's not going to take in its not going to come back with the console log statement by itself or something like that it's actually going to return an entire promise object, and that's what we're doing right here when we say return new promise. Now a promise itself takes in it because at the end of the day it's a class but whenever you create a new promise it expects a callback. So if you remember our guide on callbacks that's what this is right here. So we're passing in a function to promise and we're saying when this resolves which if you remember that means when it's successful I want you to do everything inside of here. So that's all it's saying its saying that when this occurs then I want you to do all of this cool stuff. I want you to console log out this value. I want you to say the image status and remember we're getting image status because every time we call perform upload right here we're passing in a value. You can even come down here and see it. First time we call it we're passing in uploading. Then we call it we're passing uncompressing. Next time we call it we're transferring and last. We're doing it when it's complete. So it takes in this value and then it passes it to the status and then from there, we are setting a timeout. This one is just to give us a pause. I mean if we got rid of all this it would run through but it would all look like it ran through instantly. What this is doing is it's giving us a one-second pause and it is going to be running the resolve code so it's saying that this was successful and it's passing in the image status. And this is what would be returned. We're not actually working on you know the values that are returned so it's not that big of a deal but I wanted to show how you would usually pass in the resolved status because in it we as far as what we can see this is all the code we're actually seeing. However, in a real life promise, you'd want to return a real value, so say that this image uploader was connected to like a S3 CDN or API where you're passing up image uploads and you want to be able to have them processed. This would be the value that you'd actually get which is the resolve status and then you could include that in the rest of your code. So this would return the value and then everything.

var upload;
varcompress;
var transfer;

So that's the entire promise. Now moving down we created these variables just so you know we could have variables we could assign things to and then we could you create stages for the promise so if we imagine that our upload process included uploading compressing the file and then transferring it to a different server that's what these three stages represent. So the first thing we're doing is we're calling the promise passing in uploading when this is completed. Then it hits this then method so it hits and then and if you're wondering what then takes in it takes in a callback and it takes specifically it takes in the response. So if you want to imagine what this would look like in a real-life application perform upload would be like the user clicking the upload button on the Web site that sends up uploading and it connects to the server from then the system is going to say ok well what do you want me to do next. That's where the then keyword really represents. And so we're saying I want you to start the upload when this is complete then the server is going to send back a response message. That's what our Yes is short for short for response and we could change each one of these to be a response. I just did res that's kind of the standard convention but what it means is this is what the server is responding back with.

Now we get that because this promise is going to return the value. You remember when I talked about the resolved item and what it returns that's what it's doing is it's passing this value. And then we're setting upload equal to response and then we return and we kind of continue that change. So the next thing is we're performing and upload we're taking in the value of compressing and we keep on moving down all the way until it's complete. Each one of these is simply a stage. It uses the then keyword so that it can make the whole process sequential logically and then that in turn takes in whatever the response was in the previous process. So here it takes in the response of uploading. Here it takes in the response from compressing. And here it takes in the transferring response and that is how you can work with promises in typescript.

Resources