# Javascript 동기 비동기

> Ajax는 개념적으로 비동기 통신을 위한 패러다임을 가리키며, XMLHttpRequest와 fetch는 실제로 이를 구현하는 기술이다.

HTTP 통신을 하기위해서 사용되는 브라우저 내장 객체에는 `XMLHttpRequest` (XHR) 객체가 있습니다.

XHR을 사용하면 페이지의 새로고침 없이도 URL에서 데이터를 가져올 수 있습니다. 이를 활용하면 사용자의 작업을 방해하지 않고 페이지의 일부를 업데이트할 수 있다는 장점이 있습니다.

이름에 `XML`이 들어가긴 하지만, `XMLHttpRequest`은 XML 뿐만 아니라 모든 종류의 데이터를 가져올 수 있습니다.

가장 흔히 받아오는 데이터의 종류로는 json 타입이 있습니다.

# Fetch API

Fetch API는 네트워크 통신을 포함한 리소스 취득을 위한 인터페이스를 제공하며, [`XMLHttpRequest`보다 강력하고 유연한 대체](https://developer.mozilla.org/ko/docs/Web/API/XMLHttpRequest)제입니다.

Fetch API는 [`Request`와 `Response`](https://developer.mozilla.org/ko/docs/Web/API/Request) [객체, 그리고](https://developer.mozilla.org/ko/docs/Web/API/Response) 기타 네트워크 요청에 관련된 것들을 사용하고, CORS와 HTTP Origin 헤더 행동 등 관련한 개념도 포함하고 있습니다.

[`Response`로 이행하는](https://developer.mozilla.org/ko/docs/Web/API/Response) [`Promise`인데, 서버가](https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Promise) 헤더를 포함한 응답을 하는 순간 이행합니다. 이는 **서버가 HTTP 오류 응답 코드로 응답해도 이행한다는 뜻**입니다.

```plaintext
const main = document.getElementById('main');
const addUserBtn = document.getElementById('add-user');
const doubleBtn = document.getElementById('double');
const showMillionairesBtn = document.getElementById('show-millionaires');
const sortBtn = document.getElementById('sort');
const calculateWealthBtn = document.getElementById('calculate-wealth');

let data = [];

getRandomUser();
getRandomUser();
getRandomUser();

// Fetch random user and add money
async function getRandomUser() {
  const res = await fetch('https://randomuser.me/api');
  const data = await res.json();

  const user = data.results[0];

  const newUser = {
    name: `${user.name.first} ${user.name.last}`,
    money: Math.floor(Math.random() * 1000000)
  };

  addData(newUser);
}

// Double eveyones money
function doubleMoney() {
  data = data.map(user => {
    return { ...user, money: user.money * 2 };
  });

  updateDOM();
}

// Sort users by richest
function sortByRichest() {
  console.log(123);
  data.sort((a, b) => b.money - a.money);

  updateDOM();
}

// Filter only millionaires
function showMillionaires() {
  data = data.filter(user => user.money > 1000000);

  updateDOM();
}

// Calculate the total wealth
function calculateWealth() {
  const wealth = data.reduce((acc, user) => (acc += user.money), 0);

  const wealthEl = document.createElement('div');
  wealthEl.innerHTML = `<h3>Total Wealth: <strong>${formatMoney(
    wealth
  )}</strong></h3>`;
  main.appendChild(wealthEl);
}

// Add new obj to data arr
function addData(obj) {
  data.push(obj);

  updateDOM();
}

// Update DOM
function updateDOM(providedData = data) {
  // Clear main div
  main.innerHTML = '<h2><strong>Person</strong> Wealth</h2>';

  providedData.forEach(item => {
    const element = document.createElement('div');
    element.classList.add('person');
    element.innerHTML = `<strong>${item.name}</strong> ${formatMoney(
      item.money
    )}`;
    main.appendChild(element);
  });
}

// Format number as money - https://stackoverflow.com/questions/149055/how-to-format-numbers-as-currency-string
function formatMoney(number) {
  return '$' + number.toFixed(2).replace(/\d(?=(\d{3})+\.)/g, '$&,');
}

// Event listeners
addUserBtn.addEventListener('click', getRandomUser);
doubleBtn.addEventListener('click', doubleMoney);
sortBtn.addEventListener('click', sortByRichest);
showMillionairesBtn.addEventListener('click', showMillionaires);
calculateWealthBtn.addEventListener('click', calculateWealth);
```
