<TIL> JavaScript - 동기&비동기

이민재·2021년 9월 12일
0

javascript

목록 보기
3/4

# Call Back

javascript는 동기적이기 때문에 호이스팅이 된 이후부터 작성한 순서에 맞춰서 동기적으로 실행된다.

호이스팅이란 ? var변수나 함수 선언이 위로 끌려 올라감.

"Synchronous callback"

일반적인 동기적 함수이다. 함수를 선언하고, 호출하는 즉시 원하는 결과가 나타난다.

function printImmediately(print) {
  print();
}

printImmediately(()=> console.log('hello'));

"Asynchronous callback"

동기적 함수로 실행하지 않고, 비동기적으로 사용하는 함수.
함수를 선언할 때, 원하는 값과 딜레이 시간을 인자로 받는다.

function printWIthDelay(print, timeout) {
  setTimeout(print, timeout);
}
printWithDelay(()=> console.log('async callback'), 2000);

Promise

비 동기적인 것을 실행할 때 사용하는 operation

중요한 키포인트!

1.state(상태)에 대한 이해
state: pending(promise가 만들어져서 operation을 수행한 상태)
-> fulfilled(operation을 완료한 상태) or reject(문제가 생김)

2.producer(정보 제공)와 consumer(정보 소비)에 대한 차이 이해

"Producer"

promise라는 클래스를 사용해서 만들어 보자.

//1.Producer
//new Promise가 생성될 때, executor는 바로 실행된다. 이에 주의해서 사용해야 한다.

const promise = new Promise((resolve, reject) => {
  console.log('doing something..'); //즉시 console 출력
  setTimeout(()=> {
    resolve('jev'); // 성공했을 때
    //reject(new Error('no network')); // 실패했을 때
  }, 2000);
});


promise
  .then(value=> {console.log(value)}) // value는 promise 객체가 선언한 resolve의 인자인 'jev'를 받는다.
  //catch(error => {console.log(error)}) // error는 promise 객체가 선언한 reject의 인자인 new Error를 받는다.
  //finally(() => {console.log('finally')}) // 성공하든 실패하든 상관없이 출력

"Promise Chaining"

const fetchNumber = new Promise((resolve, reject)=> {setTimeout(()=> resolve(1), 1000)})

fetchNumber
  .then(num=> num*2) // 2 after 1sec
  .then(num=> num*3) // 6 after 1sec
  .then(num => { // 값을 출력시켜도 되고, 비동기인 promise를 전달해도 됨.
  	return new Promise((resolve, reject)=> {
      setTimeout(()=> resolve(num-1), 1000)})}) 
  .then(num=> console.log(num)) // 5 after 1sec

//이렇게 알아볼 수 있듯이 .then으로 인자를 계속 연결하면서 이을수 있다.

//다른 예를 통해 다시한번 이해해보자.

const getHen= () => 
  new Promise((resolve, reject)=> {
    setTimeout(()=> resolve('닭'), 1000)})

const getEgg = hen =>
  new Promise((resolve, reject)=> {
    setTiemout(()=> resolve(`${hen}=> '계란'`), 1000)})

const cook = egg =>
  new Promise((resolve, reject)=> {
    setTimeout(()=> resolve(`${egg}=> '후라이'`), 1000)})

getHen()
    //인자 없이 'getEgg'로만 표현가능.
  .then(hen=> getEgg(hen)) //닭=> 계란
    //인자 없이 'cook'로만 표현가능.
  .then(egg=> cook(egg)) //닭=> 계란=> 후라이
    //인자 없이 'console.log'로만 표현가능.
  .then(meal=> console(meal)) //닭=> 계란=> 후라이 after 3sec

Async / Await

promise를 조금 더 간결하고 간편하고 동기적으로 실행되는 것 처럼 보이게 만드는 것
async, await을 사용하면 동기식으로 작성하는 것처럼 편안하게 작성할 수 있다.

"Async"

//기존 promise 함수를 이용한 경우
function fetchUser() {
  return new Promise(resolve,reject)=> {
    resolve('jev')})
    
fetchUser()
    .then(console.log)
  
//async를 이용한 경우
async function fetchUser() {
	return 'jev';)
    
fetchUser()
    .then(console.log)

"Await"

async function getApple() {
  await delay(1000);
  return 'apple';} // 1초 뒤에 apple을 resolve 한다.

async function getBanana() {
  await delay(1000);
  return 'banana';}  // 1초 뒤에 banana를 resolve 한다.

//이제 기존 방식대로 'apple'과'banana'를 출력하기.

function pickFruits() {
  return getApple.then(apple=> {
    return getBanana.then(banana=> `${apple}+${banana}`)})}

pickFruits.then(console.log); // 2초 뒤 apple+banana 출력

//async를 이용하여 'apple'과 'banana'를 출력하기.

async function pickFruits() {
  const apple = await getApple();
  const banana = await getBanana();
  return `${apple}+${banana}`}

pickFruits().then(console.log) // 2초 뒤 apple+banana 출력

//병렬적으로 async 사용하기

async function pickFruits() {
  //promise를 통해 각각 함수들을 불러오고, await을 통해 각 함수들 출력
  const applePromise = getApple(); // promise는 선언하는 순간 실행
  const bananaPromise = getBanana();
  const apple = await getApple();
  const banana = await getBanana();
  return `${apple}+${banana}`}

pickFruits().then(console.log) // 1초 뒤 apple+banana 2번 출력

//병렬적으로 유용하게 Promise APIs를 통해 사용하기

function pickAllFruits() {
  return Promise.all([getApple(), getBanana()]).then(fruits=> fruits.join('+'))}

pickAllfruits.then(console.log) // 1초 뒤 apple+banana 2번 출력

작동 KEY WORDS

"chrome v"

크롬 브라우저의 일부인 엔진. 이 엔진을 통해서 자바스크립트 코드는 해석되고 작동한다.

"runtime environment"

웹 브라우저는 js 엔진만으로 실행되지 않고, 브라우저가 제공하는 js 런타임 환경이 web api, queue, event loop등으로 이루어져 있는 덕분에 비동기적 실행이 가능하다.

또한 동시성을 보장하는 비동기, 논블로킹 작업들은 javascript 엔진을 구동하는 런타임 환경에서 담당한다.(브라우저 혹은 노드)

비동기 작업을 수행할 때는, 코드는 호출스택에 쌓이고 실행된다.
1. javascript의 엔진은 -> web api에게 위임
2. web api는 비동기 작업 수행 -> 테스크 큐에 넘겨준다. (이벤트 루프를 통해)
3. 콜스택에 쌓여있는 함수가 없을 때, 이벤트 루프는 테스크 큐에서 대기하고 있던 콜백함수를 콜스택으로 넘겨준다.
4. 콜스택에 쌓인 콜백함수가 실행되고, 콜스택에서 제거된다.

"js 엔진"

웹 페이지의 js 코드를 수신받아 구문을 분석하고, 구문 오류가 없다면 실행 가능한 명령으로 변환한다. memory heap과 call stack으로 구성되어 있다. 작업을 처리할 때 하나의 메인스레드에서 호출되는 함수들이 콜스택에 쌓이게 된다.
즉,싱글스레드 기반의 언어라는 말은 하나의 메인 스레드와 하나의 콜스택을 갖고 있다.

[출처]

https://www.youtube.com/watch?v=aoQSOZfz3vQ&ab_channel=%EB%93%9C%EB%A6%BC%EC%BD%94%EB%94%A9by%EC%97%98%EB%A6%AC

https://medium.com/@vdongbin/javascript-%EC%9E%91%EB%8F%99%EC%9B%90%EB%A6%AC-single-thread-event-loop-asynchronous-e47e07b24d1c

https://prohannah.tistory.com/59

https://dkje.github.io/2020/09/20/AsyncAndEventLoop/

profile
스스로 기억하기 위해서, 기록해요

0개의 댓글