시작하기 전에
❓ 싱글스레드?
자바스크립트는 싱글스레드로 동작한다.
즉, 하나의 일꾼이 코드를 읽고 수행하는 동작을 해낸다고 볼 수 있다. 또한, 자바스크립트는 동기적이다.
즉, 호이스팅이 된 이후 부터 코드가 작성한 대로 하나하나 실행된다. 따라서 효율적으로 일을 수행하기 위해서는 비동기적 관점으로 생각해야하며, 이때문에 비동기적 처리를 지원한다.❓동기/비동기
- 동기(Syncronous) : 요청을 보내고 해당 요청에 대한 응답을 받기 전 까지 다음 동작을 실행하지 않는다.
- 비동기(Ansyncoronous) : 요청을 보내고 해당 요청에 대한 응답 여부에 상관없이 다음 동작을 실행한다.
❓호이스팅? 변수와 함수 선언들이 자동적으로 제일 위로 올라가는것!
❓싱글스레드의 (직관적인) 장/단점
- 프로그래밍의 난이도가 쉽다.
- 멀티스레드보다 비용이 적고, 빠르다.
- 연산량이 많거나 구조적으로 시간이 걸리는 경우 그 작업이 완료되어야 다른 작업을 수행할 수 있다.
- 에러에 더 신경을 써야 한다.
❓callback? 다른 함수가 실행을 끝낸 뒤 실행되는 함수
이벤트 기반의 언어인 자바스크립트가 다른 명령이 끝나지 않아도 다른 이벤트를 실행하기 때문에 특정 코드가 끝나기 전까지 다른 코드가 실해되지 않게하기 위해선 콜백이 필요하다.ℹ️결론: 자바스크립트는 싱글스레드이며, 동기적이지만 비동기처리를 콜백함수, promise, async, await등을 이용해 지원한다.
function setTimeout(callBackFunction, time) {
// 실행되면 뒷방 스레드한테 가서,
// time 만큼 째고 있다가,
// 콜백으로 callBackFunction넘겨서,
// 콜스택에서 실행해!
}
문법 예시
let promise = new Promise(function(resolve, reject) {
// executor (제작 코드, '가수')
});
new Promise에 전달되는 함수는 executor(실행자, 실행함수)라고 부르며, 실행자는 new가 만들어질때 자동으로 실행된다. 이때 결과를 최종적으로 만드는 제작코드를 포함한다.
executor는 resolve나 reject 중 하나를 반드시 호출해야 하며, resolve나 reject는 인수를 하나만 받고(혹은 아무것도 받지 않음) 그 이외의 인수는 무시한다는 특성이 있다.
Promise 객체의 state, result 프로퍼티는 내부 프로퍼티이므로 [.then/.catch/.finally] 메서드를 사용해야 접근 가능하다.
(※ promise도 너무 많이 사용하게 되면 콜백지옥을 유발한다.)
.then 또는 .catch, .finally의 핸들러(어떤 경우도 상관없음)가 promise를 반환하면, 나머지 체인은 promise가 처리될 때까지 대기합니다. 처리가 완료되면 promise의 result(값 또는 에러)가 다음 체인으로 전달됩니다.
비교해보기
promise.then(f1).catch(f2);
then에서 에러가 나면 catch로 전달되고 거기서 에러 처리 (체인)
promise.then(f1, f2);
then에서 에러가 나도 이어지는 체인이 없어 에러 처리가 안됨
Promise 메서드 : Promise 클래스의 5가지 정적 메서드
1. Promise.all(promises)
모든 promise가 이행될 때까지 기다렸다가 그 결괏값을 담은 배열을 반환하며 주어진 promise중 하나라도 실패하면 Promise.all는 거부되고, 나머지 promise의 결과는 무시된다.
2. Promise.allSettled(promises)
모든 promise가 처리될 때까지 기다렸다가 그 결과(객체)를 담은 배열을 반환한다. 객체엔 아래 정보가 담긴다.
3. Promise.race(promises)
가장먼저 처리된 promise의 결과 또는 에러를 담은 promise를 반환한다.
4. Promise.resolve(value)
주어진 값을 사용해 이행/처리 상태의 promise를 만든다.
5. Promise.reject(error)
주어진 에러를 사용해 거부 상태의 promise를 만든다.
async는 function 앞에 위치한다.
async function f() {
return 1;
}
위와 같이 function 앞에 async를 붙이면 해당 함수는 항상 promise를 반환한다. 만약 promise가 아닌 값을 반환하더라도 이행 상태의 promise(resolved promise)로 값을 감싸 이행된 promise가 반환되도록 한다.
즉, async가 붙은 함수는 반드시 promise를 반환하고, promise가 아닌 것은 promise로 감싸 반환한다고 정리할 수 있다.
(※ try{} ~ catch{}를 이용해 에러 처리를 할 수 있다.)
await는 async 함수 안에서만 동작한다.
let value = await promise;
즉, 위와 같이 선언하되 async 함수 내부에 있어야 한다.
await 키워드를 만나면 promise가 처리될 때까지 기다린 후 결과를 반환한다.
▼ 주의) await는 최상위 레벨 코드에서 작동하지 않는다.
// 최상위 레벨 코드에선 문법 에러가 발생함
let response = await fetch('/article/promise-chaining/user.json');
let user = await response.json();
▼ 하지만 익명 async 함수로 코드를 감싸면 최상위 레벨 코드에도 await를 사용할 수 있다.
(async () => {
let response = await fetch('/article/promise-chaining/user.json');
let user = await response.json();
...
})();