# What is a Promise?
A Promise is an object representing the eventual completion or failure of an asynchronous operation.
# States of a Promise
A `Promise` is in one of these states:
1. `pending`: initial state, neither fulfilled nor rejected.
2. `fulfilled`: meaning that the operation was completed successfully.
3. `rejected`: meaning that the operation failed.
# How to handle a fulfilled Promise?
We don't. Promises are not meant to be handled, they're meant to be chained! If you want to consume the fulfilled value of a promise you must use the `.then` method to chain a new promise to it.
```javascript
fetch('/posts').then(response => doSomethingWith(response))
```
# What's the return value of the then() method and why is that useful?
The returned value of the `then` method is a promise that will be fulfilled with the result value of the callback provided to the method!
This is useful because it allows promises to be chained!
```javascript
Promise.resolve(1) // Promise(1) <fulfilled>
.then(value => value + 1) // Promise(2) <fulfilled>
.then(value => value + 1) // Promise(3) <fulfilled>
.then(value => value + 1) // Promise(4) <fulfilled>
.then(value => value + 1) // Promise(5) <fulfilled>
```
# What's the benefit of chaining Promises together?
A common need is to execute two or more asynchronous operations back to back, where each subsequent operation starts when the previous operation succeeds, with the result from the previous step. In the old days, doing several asynchronous operations in a row would lead to the classic callback pyramid of doom:
```javascript
doSomething(function (result) {
doSomethingElse(result, function (newResult) {
doThirdThing(newResult, function (finalResult) {
console.log(`Got the final result: ${finalResult}`);
}, failureCallback);
}, failureCallback);
}, failureCallback);
```
With promises, we accomplish this by creating a promise chain. The API design of promises makes this great, because callbacks are attached to the returned promise object, instead of being passed into a function.
```javascript
doSomething()
.then((result) => doSomethingElse(result))
.then((newResult) => doThirdThing(newResult))
.then((finalResult) => {
console.log(`Got the final result: ${finalResult}`);
})
.catch(failureCallback);
```
# How to handle a rejected Promise?
You might recall seeing failureCallback three times in the pyramid of doom earlier, compared to only once at the end of the promise chain:
```javascript
doSomething()
.then((result) => doSomethingElse(result))
.then((newResult) => doThirdThing(newResult))
.then((finalResult) => console.log(`Got the final result: ${finalResult}`))
.catch(failureCallback);
```
If there's an exception, the browser will look down the chain for .catch() handlers or onRejected. This is very much modeled after how synchronous code works:
```javascript
try {
const result = syncDoSomething();
const newResult = syncDoSomethingElse(result);
const finalResult = syncDoThirdThing(newResult);
console.log(`Got the final result: ${finalResult}`);
} catch (error) {
failureCallback(error);
}
```
# How to create your own Promise?
```javascript
const promise1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('foo');
}, 300);
});
promise1.then((value) => {
console.log(value);
// expected output: "foo"
});
console.log(promise1);
// expected output: [object Promise]
```
# How can you turn a function with a callback to a Promise?
A Promise can be created from scratch using its constructor. This should be needed only to wrap old APIs.
In an ideal world, all asynchronous functions would already return promises. Unfortunately, some APIs still expect success and/or failure callbacks to be passed in the old way. The most obvious example is the setTimeout() function:
```javascript
setTimeout(() => saySomething("10 seconds passed"), 10 * 1000);
```
Mixing old-style callbacks and promises is problematic. If `saySomething()` fails or contains a programming error, nothing catches it. This is intrinsic to the design of setTimeout.
Luckily we can wrap setTimeout in a promise. The best practice is to wrap the callback-accepting functions at the lowest possible level, and then never call them directly again:
```javascript
const wait = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
wait(10 * 1000)
.then(() => saySomething("10 seconds"))
.catch(failureCallback);
```
The promise constructor takes an executor function that lets us resolve or reject a promise manually. Since `setTimeout()` doesn't really fail, we left out reject in this case. For more information on how the executor function works, see the `Promise()` reference.
# What's an async function?
An async function is a function declared with the `async` keyword, and the `await` keyword is permitted within it. The `async` and `await` keywords enable asynchronous, promise-based behavior to be written in a cleaner style, avoiding the need to explicitly configure promise chains.
```javascript
async function someAsyncFunction() {}
```
# What does the await keyword do?
The `await` operator is used to wait for a `Promise` and get its fulfillment value. It can only be used inside an async function or at the top level of a module.
```javascript
async function someAsyncFunction() {
const result = await somePromise
}
```
# What's the benefit of using the await keyword?
The `await` keyword waits for a promise fulfillment value, besides that there's nothing special about it. The main reason for using `await` keyword is to avoid the chaining syntax of promises.
So this:
```javascript
doSomething()
.then((result) => doSomethingElse(result))
.then((newResult) => doThirdThing(newResult))
.then((finalResult) => console.log(`Got the final result: ${finalResult}`))
```
becomes this:
```javascript
async function foo() {
const result = await doSomething();
const newResult = await doSomethingElse(result);
const finalResult = await doThirdThing(newResult);
console.log(`Got the final result: ${finalResult}`);
}
```
# What happens when using the await keyword on a rejected Promise?
If the awaited promise is rejected then it's rejected value will be thrown,
and it can be caught with a `try catch` block statement:
```javascript
async function foo() {
try {
const result = await doSomething();
const newResult = await doSomethingElse(result);
const finalResult = await doThirdThing(newResult);
console.log(`Got the final result: ${finalResult}`);
} catch (error) {
failureCallback(error);
}
}
```
### Resources
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Using_promises