function doubleIt(some) {
 return some * 2;
}

function addIt(num1, num2) {
  let sum = num1 + num2;
  return doubleIt(sum);
}

console.log(addIt(5, 5)); // logs 20

A callback function is a function called inside another function.

checkInventory(order)
.then((resolvedValueArray) => {
 return processPayment(resolvedValueArray);
})
.then((resolvedValueArray) => {
  return shipOrder(resolvedValueArray);
})
.then((successMessage) => {
  console.log(successMessage);
})
.catch((errorMessage) => {
  console.log(errorMessage);
});

A common pattern with asynchronous programming in which multiple operations depend on each other to execute or must be executed in a certain order.

Function:
async function myFunc() {
  // Function body here 
  return 5
};
myFunc();


Function Expression:
const myFunc = async () => {
  // Function body here
};
myFunc();

To use the async function as a promise:
myFunc()
.then(resolvedValue => {
    console.log(resolvedValue);
  })  // Prints 5

ES8 provides a new syntax for handling asynchronous actions. Always returns a promise, if a non-promise value returned, it will return a promise resolved to that value, if nothing, returns undefined.

HTTP Requests // for browser to access different resouces on servers using the internet (different requests and responses) 
Web APIs // tools used to access the functionality and data of another application. (Browser or Third-party APIs)
REST // an architectural style for providing standards between computer systems on the web, making it easier for them to communicate  
JSON // used to facilitate data transfer in web applications, between clients and servers  

Some things to know before using the fetch() api.

Async Await GET Fetch Request:
const getData = async () => {
try {
const response = await fetch(‘https://api-to-call.com/endpoint’);        
if (response.ok){
     const jsonResponse = await response.json();
     // code to execute with JSON response                      
}
throw new Error(‘Request failed!’);            
} catch (error) {
   console.log(error)
}
};

Async Await POST Fetch Request:
const getData = async () => {
try {
const response = await fetch(‘https://api-to-call.com/endpoint’, {
method: ‘POST’,                                  
body: JSON.stringify({id: 200})
});    
if (response.ok){
     const jsonResponse = await response.json();
     // code to execute with JSON response 
}
throw new Error(‘Request failed!’); 
} catch (error) {
   console.log(error)
}
};

Using async and await with fetch requests.

setTimeout(function, 3000); // call a function after 3s
clearTimeout(timeoutID); // cancels a timeout 

Adds a timer which executes a function or piece of code once expired.

setInterval(function, 3000); // calls a function every 3s 
clearInterval(intervalID); // clears an interval 

Repeatedly calls a function or piece of code every fixed amount of time.

let myPromises = Promise.all([promOne(), promTwo(), promThree()]); 
 
myPromises
  .then((arrayOfValues) => {
    console.log(arrayOfValues);
  })
  .catch((rejectionReason) => {
    console.log(rejectionReason);
  });

To deal with multiple promises but don't care about the order they are in. Accepts an array of promises and returns a single promise. Settles in one of two ways, if every promise resolves, fullfills, the single promise is returned, an array of resolve values from each promise. If any rejects, fails, the single promise returned will reject with the reason why that promise rejected.

function helloWorld() {
  return new Promise(resolve => {
    setTimeout(() => {
      resolve('Hello World!');
    }, 2000);
  });
}

async function msg() {
  const msg = await helloWorld();
  console.log(msg);
}

msg(); // Hello World! -- after 2 seconds

A keyword added beforehand of an asynchronous operation. Halts or pause a async function until a promise is resolved.

Fetch GET: Receive Info:
fetch('http://api-to-call.com/endpoint').then(response => { // sends request  
  if (response.ok){
    return response.json(); //  converts response object into JSON
  } 
  throw new Error('Request Failed!')''
}, networkError => console.log(networkError.message)   // handles errors  
).then((jsonResponse) => {                                 
  //Code to Execute with jsonResponse   // handles success
});

Fetch POST: Send and Receive Info:
fetch('http://api-to-call.com/endpoint', {   // sends request
  method: 'POST',
  body: JSON.stringify({id: '200'})
}).then(response => {
  if (response.ok){     // converts response object to JSON
    return response.json()
  } 
  throw new Error('Request failed!');
}, networkError => console.log(networkError.message) // handles errors
).then(jsonResponse => {
  // Code to execute with jsonResponse   // handles success
});

To make network requests to APIs.

let promise = new Promise((resolve, reject) => {
  let num = Math.random();
  if (num < .5 ){
    resolve('Fullfilled');
  } else {
    reject('Rejected');
  }
});
 
const handleSuccess = (resolvedValue) => {
  console.log(resolvedValue);
};
 
const handleFailure = (rejectionReason) => {
  console.log(rejectionReason);
};
 
promise.then(handleSuccess) 
.catch(handleFailure);


Another Example:
const promise = new Promise((resolve, reject) => {
 setTimeout(() => reject(Error('Promise failed.')), 1000); 
});

promise
 .then(value => console.log(value))
 .catch(error => console.error(error))
 .finally(() => console.log('done'));

Promises are objects that represent the eventual outcome of an asynchronous operation. Can be in one of three states, pending, fullfilled, or rejected. Takes a Executor function as a parameter. Which usually has two parameters resolve and reject. When the promise runs it will pass in its own resolve() and reject() functions, Fullfilled and Rejected. Which are the be handled by .then() and .catch() promise methods which always returns a promise. Use .finally() to run a function either way, gets called in the end.

Handling Dependent Promises:
async function makeBeans() {
  let type = await shopForBeans();
  let isSoft = await soakTheBeans(type);
  let dinner = await cookTheBeans(isSoft);
  console.log(dinner);
}
makeBeans();

Handling Errors:
async function usingTryCatch() {
 try {
   let resolveValue = await asyncFunction('thing that will fail');
   let secondValue = await secondAsyncFunction(resolveValue);
 } catch (err) {
   // Catches any errors in the try block
   console.log(err);
 }
}
usingTryCatch();

Handling Independent Promises:
async function waiting() {
 const firstValue = await firstAsyncThing();
 const secondValue = await secondAsyncThing();  // waits until the first promise resolves
 console.log(firstValue, secondValue);      
}
 
async function concurrent() {
 const firstPromise = firstAsyncThing();
 const secondPromise = secondAsyncThing(); // both promises are constructed without using await, recommended 
 console.log(await firstPromise, await secondPromise); // then await each of their resolutions to print
}

Await Promise.all():
async function asyncPromAll() {
  const resultArray = await Promise.all([asyncTask1(), asyncTask2(), asyncTask3(), asyncTask4()]); 
  for (let i = 0; i<resultArray.length; i++){
    console.log(resultArray[i]); 
  }
}

Different ways to use async/await functions.

// 1. Create a new XMLHttpRequest object
var xhr = new XMLHttpRequest();

// 2. Configure the request
xhr.open('GET', 'https://api.example.com/data', true); 
// xhr.open("Method", "URL where request is going", "Asynchronous or Not") 

// 3. Set up a callback function to handle the response
xhr.onreadystatechange = function() { // xhr.onreadystatechange - event fired whenever there is a change in the AJAX Request 
    if (xhr.readyState === 4) { // xhr.readyState === 4 - means request is done and server send it's response   
        if (xhr.status === 200) { // xhr.status - returns HTTP status code of the response
            // Parse the JSON response
            var response = JSON.parse(xhr.responseText); // xhr.reponseText - returns the text response from the server
            
            // Handle the response data
            console.log(response);
        } else {
            // Handle errors
            console.error('Request failed with status:', xhr.status, xhr.statusText); // xhr.statusText - returns HTTP status text 
        }
    }
};

// Send the request
xhr.send(); // xhr.send() - method used to send the request

Asynchronous Javascript and XML, similiar to fetch, make asynchronous requests to a server and retrieve data without requiring a full page reload, but using the XMLHttpRequest object.