javascript 를 공부하다보면 동기, 비동기라는 개념을 보게 된다.
아래의 코드를 실행시키면 1,2,3,4가 순차적으로 실행된다.
console.log(1);
console.log(2);
console.log(3);
console.log(4);
앞의 명령이 끝나길 기다렸다가 앞의 명령이 다 실행되고나면 뒤의 명령들이 순차적으로 실행되는데 이런식으로 실행되는것을 우리는 '동리적으로 실행된다' 라고 한다.
그럼 이제 아래의 코드로 변경해보면
1,2,4가 출력된 뒤 5초 후 3이 출력된다.
console.log(1);
console.log(2);
setTimeout(function(){console.log(3)},5000);
console.log(3);
console.log(4);
즉, 저 setTimeout 안의 콜백함수는 메인이 되는 실행순서와는 별개로 독립적인 자기의 시간표에 따라서 동작하고 있다.
이렇듯 프로그램이 병렬적으로 실행되는 실행방식을 '비동기적으로 실행된다' 라고 한다.
Synchronous의 장점은 순차적으로 실행이 되기 때문에 어떻게 실행이 되는지를 파악하기가 용이하다.
Asynchronous는 동시적으로 여러가지가 실행되니 혼란스럽지만 훨씬 빠른 속도로 실행이 완료된다.
또한 아래의 동기, 비동기 비교 이미지2 를 보면
Synchronous는 하나의 명령이 끝날때 까지 새로운 명령은 기다리고 있지만
Asynchronous는 process_A 와 process_B 가 각자의 명령을 실행하다가 process_B의 명령실행이 끝나면 process_A 에 다시 합류하는것을 볼 수 있다.
그렇다면 위의 setTimeout을 사용한 저 코드는 전혀 실용적이지 않다.
어떠한 경우에 비동기적인 처리를 하느냐면 어떠한 명령을 실행할 떄 그 명령이 언제 끝날지 예측하기 어렵거나
주가되는 작업이 아닐떄에 비동기적인 처리를 많이 사용한다.
대표적으로는 통신을 할 떄 에 많이 사용하는데 서버와 웹브라우저가 통신할 떄 에는 그 통신에 언제 끝날지 알 수 없다.
그렇다면 그 통신이 끝날 때 까지 아무것도 안하고 있기 기다리기 보다는 다른 작업들을 먼저 진행하다가 통신이 끝나면 콜백이 호출되면서 필요한 작업들을 나중에 진행하면 훨씬 효율적일 것 이다.
예를 들어 네이버의 추천검색어기능이 그 대표적인 예시이다.
검색창에 내가 어떠한 검색어를 입력하면 비동기적으로 브라우저와 서버는 통신하여 추천검색어들을 나에게 보여준다.
-> 페이지를 리로드하지않고 JavaScript를 이용하여 브라우저와 서버가 통신하지않는 ajax 방식.
만약 추천검색어를 동기적으로 실행했다면 우리는 추천검색어가 다 뜰때까지 아무작업도 할 수 없을 것 이다.
하지만 우리는 통신을 하고 있다는 사실조차 알지 못했다.
왜냐면 비동기적으로 통신을 하고 있었기 때문이다.
자 그렇다면 이제부터 브라우저와 웹서버가 통신할 때 사용하는 fetch 라는 API 를 살펴볼텐데
이 fetch API 가 바로 Promise 를 사용한다.
이 fetch를 통해서 Promise 를 어떻게 다뤄야 하는지를 아라보쟈.
fetch('http://example.com/examle.json')
.then(res => res.json())
.then(data => console.log(data))
위는 MDN의 fetch API 사용법 예시이다.
저것의 구체적인 사용법은 천천히 알아보기로 하고
결과적으로 주소를 주고 실행을 시키면 저기 data라는 파라미터를 통해서 웹서버가 return해준 JOSN 데이터 타입을 javascript의 데이터 타입에 맞게 컨버팅한 결과를 가져올 수 있게 된다. 라는 취지의 코드이다.
중요한건 이렇게 언제 끝날지 알 수 없는 서버와의 통신은 비동기적으로 처리하는 경우가 많다.
console.log(1);
fetch('http://example.com/examle.json')
.then(res => res.json())
.then(data => console.log(data))
console.log(2);
(출력)
1
2
data
어떠한 함수를 사용하는데 return 값으로 Promise type의 값을 준다면 그 함수는 비동기적으로 동작하는 함수일 가능성이 매우 높다.
그 함수가 return 한 값은 2개의 메소드(then, catch)를 사용할 수 있다. 2개의 메소드는 모두 콜백함수를 받는다.
2-1 ReoponsePromise.then()
-> fetch 를 통한 통신 결과가 성공했을 때 then으로 전달된 콜백함수가 호출된다.
그리고 그 콜백함수가 호출되면서 통신의 결과값이 있다면 첫번째 파라미터로 받을 수 있 다.
2-2 ReoponsePromise.catch()
-> Promise 를 리턴하는 fetch 함수가 실행실패가 되었을 때 catch 안으로 전달된 콜백함수가 호출된다.
그리고 그 콜백함수의 인자로는 실패한 이유가 들어간다.
const fetched = fetch('https://jsdfsdf......');
console.log('fetched', fetched);
fetched.then(function(result){
console.log('result', result)
});
-> A Promise that resolves to a Response object.
위의 출력값과 공식문서를 통해서 알 수 있듯이
fetch 함수를 통해 fetched에 Promise type 의 객체가 return 되었고 fetch함수가 성공적으로 실행이 되면서 Response 객체를 then의 콜백함수의 인자로 넣어주게 된것이다.
이번엔 아래처럼 fetch 함수의 URL을 일부러 이상하게 써서 fetch 함수를 실패시키면 catch 메소드가 실행되고 실패한 이유에 대해 알 수 있게 된다.
const fetched = fetch('이상한 URL');
console.log('fetched', fetched);
fetched.then(function(result){
console.log('result', result)
});
fetched.catch(function(reason){
console.log('reason',reason);
})
Promise 를 사용하는 첫번쨰 이유는 비동기적인 어떤 작업을 처리할 때 그 작업이 성공했는지 실패했는지를 표준화된 방식을 이용해서 처리할 수 있도록 해주기 때문이다.
-> 성공하면 .then 으로 전달된 함수가 실행, 실패하면 .catch 로 전달된 함수가 실행
자 그럼 위의 코드를 좀 더 가독성있고 일반적으로 사용하는 방식으로 바꿔보면
fetch 는 Promise 를 return 하니까 일반적으로 변수에 담지 않고 바로 뒤에 .then 을 붙여준다.
그리고 then도 실행시키고나면 또다시 Promise 를 준다. 그리고 그것은 catch 에서 받을 수 있기 때문에 아래와 같이 변경할 수 있다.
fetch('https://www.www...l.....')
.then(resposne => console.log('resposne', resposne))
.catch(reason => console.log('reason', reason))
####################################################################
(MDN 설명)
Promise는 프로미스가 생성된 시점에는 알려지지 않았을 수도 있는 값을 위한 대리자로, 비동기 연산이 종료된 이후에 결과 값과 실패 사유를 처리하기 위한 처리기를 연결할 수 있습니다.
프로미스를 사용하면 비동기 메서드에서 마치 동기 메서드처럼 값을 반환할 수 있습니다.
다만 최종 결과를 반환하는 것이 아니고, 미래의 어떤 시점에 결과를 제공하겠다는 '약속'(프로미스)을 반환합니다.
####################################################################
정리하자면 Promise 는 2가지 사용방식이 있다.
-> then 안에 then을 사용하는 방법
-> then 안에서 Promise 를 return 하는 방법 그리고 바깥의 다음 then 과 연결시키는 방법
-> 일반적으로 사용되는 방식이다.
Javascript Promise 를 사용하게 되면 그 즉시 pending(대기중) 상태이다.
그리고 그 결과에 따라 .then 또는 .catch 안의 콜백함수를 실행해준다
그리고 그 콜백함수가 새로운 Promise 를 return 하면 다시 pending 상태가 시작되고 위의 프로세스가 반복되는것이다.
🐝