---
description: >-
  Content credits to Codecademy Intermediate JavaScript course, these are just
  my personal note taking for future references.
---

# JavaScript Asynchronous Ops - Promises

## Summary

* Promises are JavaScript objects that represent the eventual result of an asynchronous operation.
* Promises can be in one of three states: pending, resolved, or rejected.
* A promise is settled if it is either resolved or rejected.
* We construct a promise by using the `new` keyword and passing an executor function to the `Promise` constructor method.
* `setTimeout()` is a Node function which delays the execution of a callback function using the event-loop.
* We use `.then()` with a success handler callback containing the logic for what should happen if a promise resolves.
* We use `.catch()` with a failure handler callback containing the logic for what should happen if a promise rejects.
* Promise composition enables us to write complex, asynchronous code that’s still readable. We do this by chaining multiple `.then()`‘s and `.catch()`‘s.
* To use promise composition correctly, we have to remember to `return` promises constructed within a `.then()`.
* We should chain multiple promises rather than nesting them.
* To take advantage of concurrency, we can use `Promise.all()`.

## Promises Basics

The `Promise` constructor method takes a function parameter called the _executor function_ which runs automatically when the constructor is called. The executor function generally starts an asynchronous operation and dictates how the promise should be settled.

The executor function has two function parameters, usually referred to as the `resolve()` and `reject()` functions. The `resolve()` and `reject()` functions aren’t defined by the programmer. When the `Promise` constructor runs, JavaScript will pass **its own** `resolve()` and `reject()` functions into the executor function.

* `resolve` is a function with one argument. Under the hood, if invoked, `resolve()` will change the promise’s status from `pending` to `fulfilled`, and the promise’s resolved value will be set to the argument passed into `resolve()`.
* `reject` is a function that takes a reason or error as an argument. Under the hood, if invoked, `reject()` will change the promise’s status from `pending` to `rejected`, and the promise’s rejection reason will be set to the argument passed into `reject()`.

```javascript
const executorFunction = (resolve, reject) => {
  if (someCondition) {
      resolve('I resolved!');
  } else {
      reject('I rejected!'); 
  }
}
const myFirstPromise = new Promise(executorFunction);
```

* We declare a variable `myFirstPromise`
* `myFirstPromise` is constructed using `new Promise()` which is the `Promise` constructor method.
* `executorFunction()` is passed to the constructor and has two functions as parameters: `resolve` and `reject`.
* If `someCondition` evaluates to `true`, we invoke `resolve()` with the string `'I resolved!'`
* If not, we invoke `reject()` with the string `'I rejected!'`

```javascript

const inventory = {
  sunglasses: 1900,
  pants: 1088,
  bags: 1344
};

// Write your code below:
const myExecutor = (resolve, reject) => {
  if (inventory.sunglasses > 0 ){
    resolve ('Sunglasses order processed.');
  } else {
    reject('That item is sold out.');
  }
}

const orderSunglasses = () => {
  return new Promise(myExecutor)
}
const orderPromise = orderSunglasses();
console.log(orderPromise);
```

## Node setTimeout( )

* node API that uses callback to schedule tasks after a delay
* 2 parameters : callback function and delay in milliseconds

```javascript
//BASIC USE
const delayedHello = () => {
  console.log('Hi! This is an asynchronous greeting!');
};
 
setTimeout(delayedHello, 2000); // at least 2 seconds delay, setTimeout NO CAPS FOR 'O'    
//Construct ASYNCHRONOUS PROMISES
const returnPromiseFunction = () => {
  return new Promise((resolve, reject) => {
    setTimeout(( ) => {resolve('I resolved!')}, 1000);
  });
};
 
const prom = returnPromiseFunction();
```

In the example code, we invoked `returnPromiseFunction()` which returned a promise. We assigned that promise to the variable `prom`. Similar to the asynchronous promises you may encounter in production, `prom` will initially have a status of pending.

## Consuming Promises :&#x20;

### .then() method

* tells computer what to do after rejected or resolved after promise

In the case of our dishwasher promise, the dishwasher will run **then**:

* If our promise rejects, this means we have dirty dishes, and we’ll add soap and run the dishwasher again.
* If our promise fulfills, this means we have clean dishes, and we’ll put the dishes away.

![Dishwasher then method example](https://2068334946-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fow1iM27u7disHeJiSlBC%2Fuploads%2FpT9RsZzmZdTGXGpwjgBL%2Fimage.png?alt=media\&token=a966f4e8-39d1-407b-a6f5-b8d820803442)

`.then()` has 2 callback functions as arguments:

When the promise settles, the appropriate handler will be invoked with that settled value.

* The first handler, sometimes called `onFulfilled`, is a _success handler_, and it should contain the logic for the promise resolving.
* The second handler, sometimes called `onRejected`, is a _failure handler_, and it should contain the logic for the promise rejecting.

Note that it always returns a promise.

```javascript
// EXAMPLE USAGE
let prom = new Promise((resolve, reject) => {
  let num = Math.random();
  if (num < .5 ){
    resolve('Yay!');
  } else {
    reject('Ohhh noooo!');
  }
});
 
const handleSuccess = (resolvedValue) => {
  console.log(resolvedValue);
};
 
const handleFailure = (rejectionReason) => {
  console.log(rejectionReason);
};
 
prom.then(handleSuccess, handleFailure);
```

Explanation:

* `prom` is a promise which will randomly either resolve with `'Yay!'` or reject with `'Ohhh noooo!'`.
* We pass two handler functions to `.then()`. The first will be invoked with `'Yay!'` if the promise resolves, and the second will be invoked with `'Ohhh noooo!'` if the promise rejects.

```javascript
// EXAMPLE PROMISE FOR STOCK CHECKING 
//1. Stock File - Library.js
const inventory = {
  sunglasses: 0,
  pants: 1088,
  bags: 1344
};

const checkInventory = (order) => {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            let inStock = order.every(item => inventory[item[0]] >= item[1]);
            if (inStock) {
                resolve(`Thank you. Your order was successful.`);
            } else {
                reject(`We're sorry. Your order could not be completed because some items are sold out.`);
            }
        }, 1000);
    });
};
module.exports = {checkInventory};
//2. Handle Promises - app.js
const {checkInventory} = require('./library.js');

const order = [['sunglasses', 1], ['bags', 2]];

const handleSuccess = (resolvedValue) => {
  console.log(resolvedValue);
};

const handleFailure = (rejectReason) => {
  console.log(rejectReason);
};
checkInventory(order).then(handleSuccess,handleFailure);
```

### .catch() method - quite a useless function, for readability

* only takes one argument : onRejected()
* activated on reason for rejection - failure handler
* same as using .then() but only with a failure handler

```javascript
prom
  .then((resolvedValue) => {
    console.log(resolvedValue);
  })
  .catch((rejectionReason) => {
    console.log(rejectionReason);
  });
```

Explanation:

* `prom` is a promise which randomly either resolves with `'Yay!'` or rejects with `'Ohhh noooo!'`.
* We pass a success handler to `.then()` and a failure handler to `.catch()`.
* If the promise resolves, `.then()`‘s success handler will be invoked with `'Yay!'`.
* If the promise rejects, `.then()` will return a promise with the same rejection reason as the original promise and `.catch()`‘s failure handler will be invoked with that rejection reason.

```javascript
//BASICALLY
checkInventory(order)
.then(handleSuccess)
.catch(handleFailure);
```

## Composition - Chaining Promises

```javascript
firstPromiseFunction()
.then((firstResolveVal) => {
  return secondPromiseFunction(firstResolveVal);
})
.then((secondResolveVal) => {
  console.log(secondResolveVal);
});
```

Explanation :

* We invoke a function `firstPromiseFunction()` which returns a promise.
* We invoke `.then()` with an anonymous function as the success handler.
* Inside the success handler we **return** a new promise— the result of invoking a second function, `secondPromiseFunction()` with the first promise’s resolved value.
* We invoke a second `.then()` to handle the logic for the second promise settling.
* Inside that `.then()`, we have a success handler which will log the second promise’s resolved value to the console.

In order for our chain to work properly, we had to `return` the promise `secondPromiseFunction(firstResolveVal)`. This ensured that the return value of the first `.then()` was our second promise rather than the default return of a new promise with the same settled value as the initial.

```javascript
// EXAMPLE
const {checkInventory, processPayment, shipOrder} = require('./library.js');

const order = {
  items: [['sunglasses', 1], ['bags', 2]],
  giftcardBalance: 79.82
};

checkInventory(order)
.then((resolvedValueArray) => {
  // Write the correct return statement here:
 return processPayment(resolvedValueArray)
})
.then((resolvedValueArray) => {
  // Write the correct return statement here:
  return shipOrder(resolvedValueArray)
})
.then((successMessage) => {
  console.log(successMessage);
})
.catch((errorMessage) => {
  console.log(errorMessage);
});
//TERMINAL INPUT
/* $ node app.js
 All of the items are in stock. The total cost of the order is 35.97.
 Payment processed with giftcard. Generating shipping label.
The order has been shipped. The tracking number is: 473611.
$ */
```

## Promise.all() method - Concurrency to maximize efficiency

when you want all promises to be done concurrently to maximize efficiency

`Promise.all()` accepts an array of promises as its argument and returns a single promise. That single promise will settle in one of two ways:

* If every promise in the argument array resolves, the single promise returned from `Promise.all()` will resolve with an array containing the resolve value from each promise in the argument array.
* If any promise from the argument array rejects, the single promise returned from `Promise.all()` will immediately reject with the reason that promise rejected. This behavior is sometimes referred to as _failing fast_.

```javascript
let myPromises = Promise.all([returnsPromOne(), returnsPromTwo(), returnsPromThree()]);
 
myPromises
  .then((arrayOfValues) => {
    console.log(arrayOfValues);
  })
  .catch((rejectionReason) => {
    console.log(rejectionReason);
  });
```

Explanation :&#x20;

* We declare `myPromises` assigned to invoking `Promise.all()`.
* We invoke `Promise.all()` with an array of three promises— the returned values from functions.
* We invoke `.then()` with a success handler which will print the array of resolved values if each promise resolves successfully.
* We invoke `.catch()` with a failure handler which will print the first rejection message if any promise rejects.

```javascript
const onFulfill = (itemsArray) => {
  console.log(`Items checked: ${itemsArray}`);
  console.log(`Every item was available from the distributor. Placing order now.`);
};

const onReject = (rejectionReason) => {
	console.log(rejectionReason);
};

// Write your code below:
const checkSunglasses = checkAvailability('sunglasses', 'Favorite Supply Co.')
const checkPants = checkAvailability('pants', 'Favorite Supply Co.')
const checkBags = checkAvailability('bags', 'Favorite Supply Co.')
Promise.all([checkSunglasses, checkPants, checkBags])
.then(onFulfill)
.catch(onReject)
//TERMINAL INPUT
/* $ node app.js
Checking availability of sunglasses at Favorite Supply Co....
Checking availability of pants at Favorite Supply Co....
Checking availability of bags at Favorite Supply Co....
sunglasses are in stock at Favorite Supply Co.
bags are in stock at Favorite Supply Co.
Error: pants is unavailable from Favorite Supply Co. at this time. 
*/
```
