# Promises

A promise is an Javascript object that has a job: go get a particular value. A promise can be in one of three states:

* **Pending:** the promise is in the process of trying to retrieve the value
* **Fulfilled:** the promise has successfully retrieved the value
* **Rejected:** the promise was unable to retrieve the value

### Analogy

Imagine you are stuck at home with a sprained ankle, so you send your friend to the market to buy some pain medication. Your friend is the **promise**. Once your friend has left for the market, the promise is **pending**. If your friend returns from the market with medication, the promise is **fulfilled**. If your friend returns from the market *without* medication, the promise is **rejected**.

## Creating a Promise

When you create a new promise, you have to tell it what it's job is. Do this buy giving it a callback function.

```javascript
var myPromise = new Promise(myCallback)
```

The promise will pass 2 arguments into the callback: **1.** a function to run if the value is successfully retrieved **2.** a function to run if the value is not successfully retrieved

```javascript
function myCallback(resolve, reject) {
  console.log('pending...');
  if(valueToRetrieve) {
    resolve(valueToRetrieve);
  } else {
    reject('valueToRetrieve is falsey');
  }
}

var valueToRetrieve = "!!!";
var myPromise = new Promise(myCallback);
```

Once a promise is fulfilled, then the promise will represent the value it was sent to retrieve.

```javascript
console.log(myPromise);
```

## Consuming the Promise

Promises are generally *consumed* by attaching a `.then().catch()`. **.then()**

* triggered by the `resolve()` function
* handles what to do next with the retrieved data

  **.catch()**
* triggered by the `reject()` function
* handles the error

```javascript
function consumePromise(){
    myPromise
        .then(function(retrievedValue){ // will run if resolve() is called
            console.log("fulfilled! retrievedValue is:", retrievedValue);
        }).catch(function(err){ // will run if reject() is called
            console.log("wah wah :( Error:", err);
        })
}

var valueToRetrieve = "!!!";
var myPromise = new Promise(myCallback);
consumePromise();
```

Run this code to see the `.then()` callback run. Change `valueToRetrieve` to a falsey value to see the `.catch()` in action!

## Chaining Promises

You can chain multiple promises together using the `.then()` function. In the callback function of the `.then()`, just return the next promise you want to run:

```javascript
function consumeTwoPromises(){
    myPromise
        .then(function(firstRetrievedValue){
            return new Promise(function(resolve, reject){
                console.log("first retrived value: "+firstRetrievedValue);
                if(firstRetrievedValue){
                    resolve(firstRetrievedValue+"???")
                } else {
                    reject("firstRetrievedValue is falsey");
                }
            })
        })
        .then(function(secondRetrievedValue){ // will run if resolve() is called
            console.log("second retrieved value is:", secondRetrievedValue);
        }).catch(function(err){ // will run if reject() is called
            console.log("wah wah :( Error:", err);
        })
}

var valueToRetrieve = "!!!";
var myPromise = new Promise(myCallback);
consumeTwoPromises();
```

## Asyncronicity

Note that promises are asynchronous. If we add the following `console.log()` statements, they wont necessarily run in the order we'd expect. Try it out!

```javascript
function consumeTwoPromises(){
    console.log("before promises")
    myPromise
        .then(function(firstRetrievedValue){
            return new Promise(function(resolve, reject){
                console.log("first retrived value: "+firstRetrievedValue);
                if(firstRetrievedValue){
                    resolve(firstRetrievedValue+"???")
                } else {
                    reject("firstRetrievedValue is falsey");
                }
            })
        })
        .then(function(secondRetrievedValue){ // will run if resolve() is called
            console.log("second retrieved value is:", secondRetrievedValue);
        }).catch(function(err){ // will run if reject() is called
            console.log("wah wah :( Error:", err);
        })
    console.log("after promises");
}
```

How would you edit this code so that the final `console.log` statement runs *after* the promises are fulfilled?

## More Resources

* [Javascript Promises for Dummies](https://scotch.io/tutorials/javascript-promises-for-dummies)
* [cujoJS: Learning Promises](http://know.cujojs.com/tutorials/promises/)


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://romebell.gitbook.io/sei-412/javascript/js-control-flow/05promises.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
