[Pre Onboarding] 8월 12일 3주차

김종원·2021년 8월 12일
1

[Pre Onboarding]

목록 보기
6/12
post-thumbnail

[Pre Onboarding] 8월 9일

Core JavaScript 1

관련 면접 질문(정리하자)

코드보고 예상되는 순서와 그 이유

- callback 패턴과 문제점은?
- promise와 callback의 차이점은 무엇이고 각각 장단점은?
- promise란 무엇인가
- Promise.all 은 언제 쓰이는지?
- async/await와 promise의 차이는?

동기 비동기

동기(Synchronouse)
정의 : 현재 실행중인 코드가 끝나야 다음 코드를 실행
현재 실행중인 task가 종료할 때까지 다음 task가 대기하는 방식

->순서대로 실행, 너무 당연한 이야기이다.

고민할 점
장점 : 동기 처리는 코드를 순서대로 하나씩 실행하기 때문에, 실행 순서가 보장된다.
단점 : 현재 실행중인 task가 종료할 때까지, 다음 task가 대기하는 방식

alert가 전형적인 동기 함수이다.
-> 확인 버튼을 사용자가 눌러야 함수 끝난다.
누르기 전까지는 bloking되면서 멈춰있다.

비동기(Asynchronouse)
정의
현재 실행중인 코드가 완료되지 않아도, 다음 코드로 넘어감
비동기 task는 실행하라고 브라우저에 맡겨놓고, 다음 task로 넘어감

api호출하고 언제 응답이 올지는 모름

고민할점
장점 : 현재 실행중인 task가 완료되지 않아도, 다음 task를 실행하기 때문에 블로킹이 발생하지 않는다.
단점 : task의 실행 순서가 보장되지 않는다.

프론트에서의 비동기 로직

비동기 처리가 필요한 이유

  • 자바스크립트 엔진은 한 번에 하나의 task만 실행할 수 있는 Single Thread. Single Thread는 한 번에 하나의 task만 실행할 수 있기 때문에 처리에 시간이 걸리는 task를 실행하는 경우 Blocking(작업 중단)이 발생한다.
    -> 비동기를 처리하기 위해 전통적으로 콜백패턴을 사용합니다.

*AJAX(Asynchronous JavaScript and XML) 비동기 자바스크립트 와 XML
예전에는 xml(데이터 형식중하나)을 받아 화면에 전체적으로 그린다.
비동기적으로 API를 호출해서 원할때 필요한 부분만 바꾼다가 안되었음
정의 : 자바스크립트를 사용해서 브라우저가 서버에게 비동기 방식으로 데이터를 요청하고
응답한 데이터를 수신하여 웹페이지를 일부 동적으로 갱신하는 것.
fetch, awake 다 ajax

동기, 비동기 관련 키워드(연관되어 공부하자.)

  • 실행컨텍스트
  • 이벤트루프
  • 스택/큐

콜백함수

정의 : 함수의 매개변수가 함수일 때 매개변수로 받은 함수를 콜백함수라고 부른다!!!
참고 : 링크텍스트

Promise

1. Promise - resolve, reject

Promise -> 클래스이다 대문자

  • Promise는 비동기 동작을 처리하기 위해 ES6에 도입되었다. (처음엔 혁명 느낌)
  • Promise는 클래스다.
  • Promise 클래스를 인스턴스화 해서 promise 객체를 만든다.
  • 반환된 promise로 원하는 비동기 동작을 처리한다.
  • Promise는 일단 state와 resolve, reject 함수를 이해하면 된다.(꼭 이해하기)

Promise 구현하기

let promise = new Promise(function(**resolve**, **reject**) {
	// 여기 비동기 로직을 작성하는것! 시키고 나중에 하고 싶은 로직 작성
	// 시켜놓고 언제 완료될지 모르는 로직!
});
  • resolve는 성공했을 때 실행할 함수(콜백함수)

  • reject는 실패했을 때 실행할 함수(콜백함수)

  • 참고로, resolve, reject 미리 정의하지 않아도 자바스크립트 엔진에서 미리 정의 해놓는다.

  • 그래서 전달 안해도 호출에 문제 없음.


    ```jsx
    let promise = new Promise(function(resolve, reject) {
    	resolve();  // 에러 안 납니다.
    	reject();
    	console.log('실행 됨');
    });
    ```

resolve 이해하기

예제

let promise = new Promise(function(resolve, reject) {
	// 여기 비동기 로직을 작성!
	// 시켜놓고 언제 완료될지 모르는 로직!

	// 완료 하면 -> resolve 호출
  // 비동기 동작 실패 하면 -> reject 호출
});

promise.then(function() {
	// 이 함수가 바로 위의 resolve 입니다.
	// 위의 비동기 로직이 성공하면 호출 됩니다!
});
let promise = new Promise(function(resolve, reject) {
    setTimeout(function() {
				// resolve 함수에 인자 넘기면
        resolve('hello world');
    }, 2000);
});

// resolve로 넘기는 콜백함수의 매개변수로 받을 수 있다.
promise.then(function(msg) {
    console.log(msg);  // 2초 뒤에 hello world!
});

reject 이해하기

let promise = new Promise(function(resolve, reject) {

});

// then 인자 둘 다 cb 함수
// 첫 번째는 성공했을 때 실행할 resolve 함수 정의
// 두 번째는 실패했을 때 실행할 reject 함수 정의
promise.then(function() {}, function() {});
let promise = new Promise(function(resolve, reject) {
	setTimeout(function() {
				// 실패한 건 아니지만, 실패했다고 가정하고 reject 호출
        reject('으악!');
  }, 2000);
});

promise.then(function() {
	console.log('resolve');
}, function(msg) {
	console.log('reject', msg);
});

2. Promise Chaining

  • 여러 개의 비동기 작업을 순차적으로 해야하는 경우가 많다.
  • 순차적으로 각각의 작업이 이전 단계 비동기 작업이 성공하고 나서 그 결과값을 이용하여 다음 비동기 작업을 실행해야 하는 경우
// 요런 느낌
getProducts()   // 상품 가져오고
	.then(getComments)   // 그리고 후기 가져오고(끝나고 실행)
	.then(getLikes)   // 그리고 좋아요 가져오고(끝나고 실행)

then의 cb의 반환 값

then의 콜백함수(handler function 이라고도 함)는 여러 타입의 값을 반환할 수 있다.

값의 반환

let promise = new Promise(function(resolve, reject) {
    setTimeout(function() {
        resolve(1);
    }, 1000);
});

promise
	.then(function(first) {
	  console.log('first', first);
	  return 2;
	}).then(function(second) { 
		console.log(second);
	});

promise 반환

let promise = new Promise(function(resolve, reject) {
    setTimeout(function() {
        resolve(1);
    }, 1000);
});

promise
	.then(function(first) {
	  console.log('first', first);
	  return 2;
	})
	.then(function(second) { 
		console.log('second', second);
		
		return new Promise(function(resolve, reject) {
        setTimeout(function() {
            resolve(3);
        }, 1000);
    });
	})
	.then(function(third) {
		console.log('third', third);
	});

리턴값이 일반값이면 다음 then에서 매개변수로, promise면 그 다음 then이 resolve가 된다.

Promise로 바꾸기

$.get('https://api.test.com/proudcts', function(response) {
	var firstProductId = response.products[0].id;

	$.get('https://api.test.com/proudct/comments?id='+firstProductId, function(response) {
		var firstCommentId = response.comments[0].id;
	
		$.get('https://api.test.com/proudct/comment/likes?id='+firstCommentId, function(response) {
			var likes = response.likes;
			var likesCount = likes.length;

			// 첫번째 상품의 -> 첫번째 후기의 좋아요 수 화면에 적용!
		});
	});
});
  • $말고 promise 반환할 api 함수 필요.
  • $ 대신에 axios 사용합니다. fetch/axios 함수는 promise를 반환한다.
  • axios()와 new Promise()는 똑같다.
axios('https://api.test.com/proudcts')
  .then(function(response) {
    let firstProductId = response.products[0].id;
		
		return axios('https://api.test.com/proudct/comments?id='+firstProductId);
  })
  .then(function(response) {
		let firstCommentId = response.comments[0].id;
    
		return axios('https://api.test.com/proudct/comment/likes?id='+firstCommentId)
  })
	.then(function(response) {
			let likes = response.likes;
			let likesCount = likes.length;
  });

3. Promise - state

Promise 3가지 상태

  • promise 객체는 "상태"를 갖고 있습니다.
  • Pending(대기): 비동기 처리 로직이 아직 완료되지 않은 상태
  • Fulfilled(이행): 비동기 처리가 완료되어 프로미스가 결과 값을 반환해준 상태
  • Rejected(실패): 비동기 처리가 실패하거나 오류가 발생한 상태

4. Promise - 에러 처리

에러 처리 - reject

let promise = new Promise(function(resolve, reject) {
	setTimeout(function() {
      reject('으악!');
  }, 2000);
});

promise.then(function() {}, function(msg) {
	console.log(msg);
});

에러 처리 - catch

let promise = new Promise(function(resolve, reject) {
	setTimeout(function() {
        reject('으악!');
  }, 2000);
});

promise
	.then(function() {})
	.catch(function(err) {
		console.log(err);
	});
  • catch로 받는 것이 가독성이 조금 더 좋습니다.
  • reject handler와 catch 방식은 똑같습니다.

5. Promise - 마무리

혼자 공부해보기

  • promise.finally()
  • Promise.all()

Promise.all()

여러 프로미스를 다 하고 그다음에 하고 싶은 경우

Promise.all([
  new Promise(resolve => setTimeout(() => resolve(1), 9000)), // 1
  new Promise(resolve => setTimeout(() => resolve(2), 2000)), // 2
  new Promise(resolve => setTimeout(() => resolve(3), 1000))  // 3
]).then(console.log);

이럴때 많이 사용한다/

let urls = [
  'https://api.github.com/users/iliakan',
  'https://api.github.com/users/remy',
  'https://api.github.com/users/jeresig'
];

// map every url to the promise of the fetch
let requests = urls.map(url => fetch(url));

// Promise.all waits until all jobs are resolved
Promise
	.all(requests)
  .then(responses => responses.forEach(
    response => alert(`${response.url}: ${response.status}`)
  ));

async & await

  • async function은 ES8에 도입되었으며, 비동기 함수를 선언합니다.
  • async function은 promise를 반환하기 때문에 Promise를 잘 알아야 합니다.
  • await를 쓰려면 async 함수 안에 꼭 있어야 합니다!
  • 즉시 실행함수(Immediately invoked function expression, IIFE)
    알아두기

async & await 관련 키워드

  • 제너레이터
  • iterator
  • iterable object
profile
발전하기위한 기록

0개의 댓글