 Are you wondering what these JavaScript promises are? Hi, I'm Sarah Clark, and I'm here to show you how they work and when to create your own. Promises are designed to make asynchronous programming easier. They replace nested callbacks and event handlers to make asynchronous code look like synchronous code. Your code becomes easier to read and error handling becomes much simpler. If you're not sure what I mean about synchronous and asynchronous, let me give you an example. Most of the code you write is synchronous, like this. In synchronous code, the browser completes each statement before moving on to the next. In this case, the browser completes line one before running line two. Synchronous code doesn't work well when you have a slow operation, such as loading a file. In that case, the browser uses asynchronous code to perform the operation in the background. Before promises, an asynchronous action could send an event or call a callback when done. In this example, we're going to get index.html and write it to the console. We're using XML HTTP request, a legacy networking API. First, we need to write an event handler. This is called when the request completes. It takes a response event and logs the text. Now we can create the request object, attach the event handler, tell it what we want to do, and start the request. When this finishes, it will trigger the event handler sometime in the future. This code has a few problems. It only handles success. If you want to detect errors, you need another event handler. It also becomes harder to read as it becomes more complex. The newer fetch API uses promises for the same task. This looks like synchronous code, but it's actually two asynchronous calls in a row. First, we call fetch with a URL. It immediately returns a promise. We immediately call dot then on the promise and register a callback. When fetch gets its result, it's passed into this function. This is an ordinary synchronous function that takes a single parameter and returns a new value. When you call dot then, the promise registers a callback and returns a new promise. You can register one callback per promise, not counting error handling. We'll see that later. Now we take the promise from the first then and register a callback on it. This takes some text and writes it to the console. By itself, this is a toy example. I replaced five lines of code with three. But the beauty of promises is that you can replace multiple event handlers or nested callbacks with simple code and easy error handling. Do you want to handle errors? It only takes one line. If anything goes wrong above, the catch statement will get the exception. Do you need to transform data? Promises form a pipeline with the result of a promise passed into its callback. The result of that callback, registered via dot then, is passed into the next one. If you're familiar with UNIX pipes, this is the same idea. Let's take a step back and look at how promises work at runtime. This assumes you have called some function that gives you a promise. A promise is just an object with a special API. It has to implement dot then and space for a result. It's normally returned from an asynchronous call. When you get a new promise, it's usually waiting for a value from some operation. This is called the pending state. You can call dot then and dot catch to register result and error handlers. When the operation completes with a value, it's said to resolve with that value. The value is locked into the promise and the promise is fulfilled. If you register to callback with dot then, it will be called with this value and its result goes into a new promise. In the same way, if there's an exception in the underlying code, the promise is said to be rejected with an error. If you register to callback with dot catch, it will be called with the error. Most developers register a catch on the last promise in the chain, though there are some power user tricks you can do with catches in the middle. We'll talk about those in a later episode. Note that you can only use a given promise once, but if you set up a chain of functions, you can always run it again with a new promise at the start. In a later episode, we'll show you how to run multiple promises at the same time, but for now, I want to talk about error handling. This code should look familiar by now. Get a file, extract the text and log it, but what if something goes wrong? I can add a catch, but there are several errors that could trigger it. For example, even if a fetch fails, it still returns a result. Calling result dot text might not do what you expect. When you expect a possible error, such as file not found, add a step right after. This step checks for the error and can throw an exception. If this doesn't throw an exception, it should return the response for the next step to use. If you forget the return, it will return undefined. And one last note, if you are using ES 2017 or later, the async and await keywords make using promises easy. You put the await keyword in front of anything that returns a promise. This code will then create the callbacks to run the next line when done. You must put the async keyword on any function that uses await. This triggers the automatic promises support. You can call another async function using the await keyword like anything else that returns a promise. Now you should be able to get a promise, set up a chain of calls to follow it, and handle errors. This is enough to handle most PWA tasks. If you want more practice, see the Code Lab. We have some more advanced techniques to show you, beginning with other uses for fetch. Keep watching to learn more about fetch. I'll see you over there.