JS에서는 많은 것에 대해 참인지 거짓인지를 판별할 수 있다.
true라 나오는 것 : [], {}, 0을 제외한 숫자, infinity, 비어있지 않은 문자열 -> truthy
fasle라 나오는 것 : Null, NaN, 0, undefined, ""(빈 문자열) -> falsy

if문은 다음과 같이 표현하는 것이 가능하다.
조건 ? 참일 때 코드 : 거짓일 때 코드

short-circuit evaluation은 and나 or 등에서 왼쪽이 참이거나 거짓일 경우 뒷부분은 보지 않아도 되는 것을 말한다.
ex) console.log(name || "이름을 입력해주세요") 와 같이 name에 빈 문자열이 올 경우에만 뒷 부분이 실행된다.

비 구조화 할당이란 굉장히 빠르고 간단하게 값을 다른 변수에 담는 것을 말한다.
let a = [1,2,3]
let [b,c,d,e,f=10] = a
각 변수를 출력 할 경우 b,c,d에는 각 a[0],a[1],a[2]가 담기로 e는 undefined, f는 기본값인 10이 출력된다.
즉 배열에서 비구조화 할당은 순서를 기준으로 할당된다.

let a = {name : 'aaa', age : 24}
let [age, name :re_name, gender] = a
각 변수를 출력할 경우 age는 24, re_name은 'aaa', gender은 undefined가 출력된다.
즉 객체에서 비구조화 할당은 키값을 기준으로 할당하며 순서는 상관없다.

이 비구조화를 응용하면 [a,b] = [b,a] 와 같이 swap을 굉장히 편리하게 할 수 있다.

null의 type은 object다 => 과거에 실수로 이렇게 했는데 결국 변경하지 못함.
a[]을 선언한 후 a[100] = 1 하면 a.length = 101이다.

...은 스프레드 연산자라고 한다. 객체의 프로퍼티와 값을 그대로 전달한다.

동기는 기본적인 코드의 실행 방식으로 한 연산이 끝난 후 아래 연산이 이루어진다.
이전 작업이 오래 걸리더라도 다음 작업을 실행할 수 없다. 이를 블로킹 방식이라고도 한다.
문제점은 중간에 너무 오래 걸리는 작업이 있는 경우 문제가 생길 수 있다.
예를 들어, 웹페이지가 모두 동기 방식으로 작성되어 있다면 중간에 용량이 큰 사진이 들어있는 경우 사진을 전부 불러올 때까지 아래에 글들은 나오지 않는다.

이를 해결하기 위해 비동기작업, 논블로킹 방식이 있다.
여러개의 작업을 동시에 실행시킨다. 동기와 달리 각 작업이 잘 완료되었는지 알 수 없으므로 콜백함수를 사용해 잘 동작한 것을 확인한다.

	console.log("시작");

	(function a() {
      setTimeout(()=>{
       	console.log("중간");     
      },2000); 
    }) ();// 이를 iffe 즉시 실행 함수라 함.

	console.log("끝")

순서대로 보면 Call Stack에 anonymous가 먼저 쌓인다.(어느 글에서는 Main Context라고도 한다.)
Call Stack에 console.log("시작");이 쌓인 후 실행되고 빠진다.(콘솔에 시작이 출력된다.)
Call Stack에 a 함수가 쌓인 후 실행되고 빠진다. setTimeout의 인자들이 Web Api에 넘어간다. 이와 동시에 2초 카운트가 실행된다.
Call Stack에 console.log("끝");이 쌓인 후 실행되고 빠진다.(콘솔에 끝이 출력된다.)
먼저 쌓였던 anonymous가 빠진다.
2초 후 console.log("중간");가 Task Queue로 넘어간다.
event loop에 의해 Call Stack이 모두 비어있으므로 console.log("중간");이 Call Stack에 쌓인 후 빠진다.(콘솔에 중간이 출력된다)

콘솔에는 다음과 같이 출력된다.

시작
끝
중간

위 코드에는 콜백함수를 사용하지 않았다.

	function taskA(a, b, cb) {
      setTimeout(
          () => {
              let res = a + b;
              cb(res);
          }, 2000
      );
	}

	taskA(1,2,(result) => console.log(result));

다음과 같이 콜백함수를 사용한다.
(result) => console.log(result)
이 부분이 콜백함수인데, 2초 후 res에는 1+2를 한 값인 3이 담긴다.
cb(res)는 콜백함수인 (result) => console.log(result) 이 구문을 실행한다.
즉 콘솔에 3이 출력된다.

여기에서는 콜백을 하나만 사용했지만 만약 이 동작으로 나온 값을 다시 콜백하는 함수들이 여러개 있을 경우 코드는 굉장히 복잡하고 더러워진다.

이를 해결하는 것이 promise다.
이에 앞서 비동기 작업은 3가지 상태를 가질 수 있다.
pending(대기), fulfilled(성공), rejected(실패)

pending -> fulfilled 되는 과정을 resolve(해결)
pending -> rejected 되는 과정을 reject(거부)

앞선 코드를 promise를 사용해 다시 작성하면

	function taskA(a, b) {
      const execute = new Promise((resolve, reject) => {
        setTimeout(
          () => {
            if (a !== 0 && b !== 0){
              let res = a + b;
              resolve(res);
            }else{
              reject('두개의 값중 0이 포함되어 있습니다.');
            }
          }, 2000
        );
      });
      return execute
	}

	taskA(1,2).then((res)=>console.log(res)).catch((err)=> console.log(err));

	let result  = taskA(1,2).then((res) => res);

실패할 경우도 보여주기 위해 코드를 조금 수정했다.
보면 a와 b 모두 0이 아니어야만 성공한다.
.then은 resolve 된 값을 가져온다. .catch는 반대로 reject 된 값을 가져온다.

또한 이는 값으로 변수에 저장에 원할 때 사용할 수 있다는 차이점이 있다.

앞서 말했듯이 비동기 작업은 모든 동기 작업이 완료된 후에 Task Queue에서 Call Stack으로 옯겨져 실행된다.

다만 만일 그럼 비동기함수로부터 값을 받아서 해당하는 값을 추후 코드에서 사용해야한다면 어떻게 할까.

await을 사용하면 비동기 함수 내부에서 다른 비동기 함수를 동기 함수처럼 사용할 수 있다.

function delay(ms) {
    return new Promise((resolve) => {
        setTimeout(() => resolve(), ms);
    });//이는 Promise((resolve) => setTimeout(resolve, ms))와 동일함.
}

async function helloAsync() { //이 함수는 자동으로 프로미스를 반환함.
    return delay(3000).then(() => {
        return 'hello Async';
    }); // 이 값은 resolve 함수의 인자로 전달됨.
}
//async 함수는 자동으로 프로미스를 반환함. 이때 return된 값은 resolve 함수의 인자로 전달됨.

//위 함수를 조금 더 간단히 표현하기 위해 await을 사용하면 
async function helloAsync2() {
    await delay(3000); // 비동기 함수를 동기 함수인것 처럼 실행.
    //즉 3초가 지난 후 아래 값을 return함. async 함수 내에서만 사용가능.
    //await 코드가 붙은 비동기 함수가 실행되기 전에는 helloAsync2 함수는 멈춰있음.
    return 'hello Async2';
}

(async function main() {
    const res = await helloAsync(); // 다음과 같이 호출하는 함수만 따로 빼서 사용 가능.
    console.log(res);
}) ()

총 2가지 상황에서 사용되는 것을 표현했는데 함수 helloAsync2는 함수 helloAsync를 보다 간단하게 표현한 것이다. 단순하게 기다리는 비동기 함수 delay가 실행된 후 return해야 하므로 .then을 써도 되고 await을 사용해 비동기 함수 내에서 delay함수가 먼저 실행되고 후에 return문을 실행한다.

아래는 앞서 말했듯이 비동기 함수 내에서 동기적으로 먼저 비동기함수를 실행한 값을 후에 사용해야할 때를 표현한 것이다.

api라는 것에 대한 글은 굉장히 많다. 그래서 간단히 말하면 client와 server간에 데이터를 주고받기 위한 코드다.
api 호출은 client가 서버에 데이터를 요청하고 전달받는 것을 말한다.

async function getData() {
    let rawResponse = await fetch('https://jsonplaceholder.typicode.com/posts'); //fetch는 api 호출을 도와주는 내장함수로 promise를 반환한다.
    let jsonResponse = await rawResponse.json(); //await는 promise가 resolve될 때까지 기다렸다가 resolve된 값을 반환한다.
    console.log(jsonResponse);
}

getData();

이를 분석하면 fetch과 .json()는 비동기 함수이다.
각 과정에서 나온 값을 사용해야하는 동기적 코드이므로 비동기 함수인 getData()를 만들고 await을 사용해 동기적으로 작동하게 한다.

fetch는 서버로부터 응답을 받을때 덩어리를 받는다. 하지만 저 url에서 우리는 json 형태로 작성된 데이터 값을 받아오고 싶으므로 fetch로 return된 promise 타입의 값에 .json() 내장함수를 사용하여 원하는 값을 얻는 것이다.

profile
입니다.

0개의 댓글