post-custom-banner

8/12(목) 프리온보딩 수업내용을 정리한 내용 입니다.

동기 : 현재 실행 중인 코드가 끝나야 다음 코드를 실행

지금 실행중인 task 가 종료될 때까지, 다음 task 가 대기하는 방식

장점 👉🏻 실행 순서가 보장된다.
단점 👉🏻 지금 task가 종료될때까지 다음 task 가 실행 될 수 없다. (blocking 된다 라고 표현)

비동기 : 현재 실행 중인 코드가 완료 되지 않아도, 다음 코드로 넘어감

비동기 task는 실행하라고 브라우저에 맡겨놓고, 다음 task로 넘어감

장점 👉🏻 블로킹(blocking)이 발생하지 않는다.
단점 👉🏻 task 실행 순서가 보장 되지 않는다.

비동기 처리가 필요한 이유
자바스크립트 엔진은 한번에 한번의 task 만 실행할 수 있는 single Thread(싱글쓰레드),
처리시간이 걸리는 task를 실행하는 경우 Blocking(작업중단)이 발생할 수 있다.

콜백함수의 등장
비동기를 처리하기 위해 전통적으로 콜백패턴(레거시적 방법)을 사용한다.

AJAX (fetch, axios, asnyc, promise...)

AJAX 자바스크립트를 사용하여 브라우저가 서버에게 비동기 방식으로 데이터를 요청하고,
응답한 데이터를 수신하여 웹페이지를 일부 동적으로 갱신한다.

Quiz!

setTimeout(()=>{
  console.log("1")
},0)
console.log('2')
for(let i =0; i<3; i++){
  loop();
}
setTimeout(()=>{
  console.log("3")
},0)
console.log('4')

function loop(){
  console.log("5")
}

정답
"2","5","5","5","4","1","3"
비동기는 동기호출 이후 호출된다.

callback 콜백함수;

함수의 매개변수가 함수일때, 그 매개변수를 콜백함수라 한다.
HOC(고차함수) 👉 매개변수를 함수로 받은 함수, 인자를 컨포넌트로 받아서 컴포넌트를 반환하는 것.

function showMessage(message, closeFn){
	closeFn(true)
}
// showMessage : 고차함수
// closeFn : 콜백함수
[1,2,3].map(el => el*2) 
//< el=>el*2 자체를 콜백함수라 함

단, 콜백함수라 해서 항상 비동기에 쓰이진 않는다.

callback 패턴과 문제점은?

callback안에 callback이 계속 이어지는 모습인 콜백지옥 패턴을 나타낼 수 있다.

promise란 무엇인가

비동기 동작을 처리 하기 위해 도입 (ES6)
Promise 👉 javascript 내장 클래스
클래스 👉 객체 만드는 공장, 객체를 만들때 그것을 인스턴스 한다고한다.

state, resolve, reject, finally 함수 이해하기

x

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

let promise = new Promise(function(resolve, reject) {
	resolve();
	reject();
	console.log('실행 됨');
});

resolve 이해하기 👀

// new Promise 로 객체를 생성해 promise 에 넣어둔 것!
let promise = new Promise(function(resolve, reject){
  // 여기 비동기 로직 작성
  // 완료하면 => resolve 호출
  // 비동기 동작 실패 하면 => reject 호출
});

promise.then(function(){
  // 이 함수가 바로 위의 resolve
  // 위의 비동기 로직이 성공하면 호출 됩니다!
});

promise.finally(function(){
 //finally() 메소드는 Promise 객체를 반환합니다. 
 //Promise가 처리되면 충족되거나 거부되는지 여부에 관계없이 
 //지정된 콜백 함수가 실행됩니다.
 // settled (fulfilled or rejected)
});
-----------------------
  
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 이해하기 👀

// new Promise 로 객체를 생성해 promise 에 넣어둔 것!
let promise = new Promise(function(resolve, reject){
  // 여기 비동기 로직 작성
  // 완료하면 => resolve 호출
  // 비동기 동작 실패 하면 => reject 호출
});

promise.then(function(){
  // 이 함수가 바로 위의 resolve
  // 위의 비동기 로직이 성공하면 호출 됩니다!
}, function(){
  // 이 함수가 바로 위의 reject
  // 위의 비동기 로직이 실패하면 호출 됩니다!
});

---------------------------------
  
let promise = new Promise(function(resolve, reject) {
    setTimeout(function() {
	// resolve 함수에 인자 넘기면
        reject('ERROR');
    }, 2000);
});

// resolve로 넘기는 콜백함수의 매개변수로 받을 수 있다.
promise.then(function() {
  console.log('resolve');
}, function(msg){
  console.log('reject', msg);
});

// 출력값 reject , ERROR

🚧 주의

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

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

// 한번 호출 하면 then 속으로 들어가서 다시 돌어가지 않는다.

QUIZ ✍🏻

let promise = new Promise(function(resolve, reject) {
    setTimeout(function() {
        console.log(1);
        resolve(2);
        console.log(3);
        resolve(4);
    }, 1000);
});

promise.then(function(data) {
    console.log(data);
});

// 출력값 1,3,2
-------------------------------------------------------

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

  setTimeout(function () { 
		resolve(2);
	}, 1000);
});

promise.then(function(data) {
    console.log(data);
});

// 1

promise Chaining

여러 개의 비동기 작업을 순차적으로 해야하는 경우가 많다.

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);
	});

// 출력값 'first' , 1 , 2
// then 자체가 promise를 반환한다고 볼 수 있다.

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

promise 3가지 상태

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

promise 에러처리

function job() {
    return new Promise(function(resolve, reject) {
        reject();
    });
}

job()
	.then(function() {
    console.log(1);
	})
	.then(function() {
    console.log(2);
	})
	.then(function() {
    console.log(3);
	})
	.catch(function() {
    console.log(4);
	})
	.then(function() {
    console.log(5);
	});
    
  // 4,5
function job(state) {
    return new Promise(function(resolve, reject) {
        if (state) {
            resolve('success');
        } else {
            reject('error');
        }
    });
}

job(true)
	.then(function(data) {
    console.log(data);

    return job(false);
	})
	.catch(function(error) {
    console.log(error);

    return 'Error caught';
	})
	.then(function(data) {
    console.log(data);

    return job(true);
	})
	.catch(function(error) {
    console.log(error);
	});

// 출력값 success > error > Error caught > success 

promise all ✍🏻

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}`)
  ));

// 배열 형태로 반환된다.

promise race ✍🏻

promise.all은 작업들이 다 끝난이후 배열로 반환되는 반면,
promise.race 는 가장 먼저 완료된 것을 결과값으로 반환하는 함수이다.(하나라도 이행 또는 거부상태일때 완료함)

promise.all 의 경우 거부상태가 있을때 바로 반환 🚂

IIFE 즉시 실행 함수

(function () {
	// 내용
})();

(() => {
	// 내용
})();

(async function() {
	// 내용
})();

(async () => {
	// 내용
})();

react useEffect 안에서 활용 될 수 있다.🚦
useEffect 훅 안에서 비동기 사용하기

예외처리

(async () => {
	try {
	  let productResponse = await fetch('https://api.test.com/proudcts');
	  let firstProductId = productResponse.products[0].id;

	  let commentResponse = await fetch('https://api.test.com/proudct/comments?id='+firstProductId);
		let firstCommentId = commentResponse.comments[0].id;

	  let likeResponse = await fetch('https://api.test.com/proudct/comment/likes?id='+firstCommentId);
		let likesCount = likeResponse.likes.length;
	} catch(error) {
		console.log(error);
	}
})();

Promise 관련 면접 예상질문

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

비동기와 동기 관련된 주제는 실제 업무중에도 정말 많이 사용 되고 여러 오픈소스에서도 쉽게 사용되는것을 찾을 수 있지만, 깊게 들어가다보면 헷갈리거나 복잡한 부분이 많이 있다.
간단한 것 같지만 여러가지 방식으로 사용될 수 있기 때문에 계속해서 공부하며 활용 하는 연습을 하기!

이미 알고 있던 내용도 있었지만 프리온보딩 수업 이후 더욱 확실이해하게되고 헷갈릴 수 있는 개념들을 콕콕 집어주셔서 머리속에 명확하게 정리 할 수 있어 좋았다.

referance

https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Promise/finally
https://www.notion.so/wecode/Core-JavaScript-1-b649b11a990148228ba61ea4c4f4efb0

profile
모르는것은 그때그때 기록하기
post-custom-banner

1개의 댓글

comment-user-thumbnail
2023년 4월 10일

안녕하세요 덕분에 Promise에 대해 조금 더 알게 되었어요!
저같은 응애 개발자들도 이해하기 쉽게 알려주셔서 좋네요ㅎㅎ
그런데 한가지 했갈리는? 질문이 있는데요 "reject 이해하기" 부분에서 resolve에 전달한다고 하셨는데 이 부분은 단순 오타인건가요?
그게 아니라면 혹시 왜 reject가 아니라 resolve에 전달되어야하는건가요??

답글 달기