[javascript] 동기와 비동기

chosh·2021년 12월 7일
0

동기와 비동기에 설명하기 앞서서 자바스크립트 엔진은 싱글 스레드로 한번에 한가지 작업만 실행 할 수 있다.

동기

코드를 위에서 아래로 순차적으로 실행하게 되는데, 싱글스레드 특성상 한번에 한가지 작업만 실행 할 수 있다.

비동기

코드가 병렬적(?)으로 실행되는 것으로, 코드를 위에서 아래로 실행하면서 특정 코드를 백그라운드에서 연산하라고 명령만 내리고, 다음 코드를 실행하게 된다.

비동기와 싱글스레드

싱글 스레드 특성상 한번에 한가지 작업만 실행 할 수 있지만, 비동기처리를 통해서 병렬적으로 연산을 시켜준다.

병렬적으로 처리 되는 원리

코드를 순서대로 실행을 하면서, 비동기처리의 코드를 만나면 코드를 연산하라는 명령을 내려놓고, 다음 코드를 실행한다.

비동기 처리된 코드는 연산이 완료되면 실행컨텍스트를 생성하여 큐에 쌓고,
코드가 끝까지 실행된 후에 큐에 쌓인 실행컨텍스트를 스택에 옮겨서 실행

코드 연산이 병력적으로 되고, 실행은 싱글스레드 이기 때문에 하나씩 실행이 된다

비동기 처리

비동기 처리에는 3가지 방법이 있다.

1. 콜백함수

setTimeout 함수를 이용한 콜백함수 실행

console.log('a');
setTimeout(function() {
  console.log('b');
},1000);
console.log('c');
console.log('d');
console.log('e');
// a c d e b

setTimeout에 실행할 코드가 들어있는 함수를 콜백으로 전달하면,

위에서 부터 순차적으로 실행하다가
setTimeout함수를 만나고 백그라운드에서 셋팅한 시간동안 연산을 명령하고,
다음코드를 실행 하기 때문에 결과값이
a, c, d, e, b 로 출력된다.

주의점

무거운 코드안에서 작동시킬때에는 코드를 파싱하는 시간보다 셋팅시간이 길어야 원하는 때에 콜백을 실행시킬 수 있다.

단점

콜백함수로 비동기적으로 실행되도록 하게 되면,
코드 이후의 순차적으로 진행되는 작업이 있을때 가독성이 떨어진다.

setTimeout(function() {
  console.log('a');
  setTimeout(function() {
    console.log('b');
    setTimeout(function() {
      console.log('c');
      setTimeout(function() {
        console.log('d');
        setTimeout(function() {
          console.log('e');
        },1000);
      },1000);
    },1000);
  },1000);
},1000);

이렇게 가로로 길어지는 문제가 있고,
실행 되는 순서를 볼 때,
위의 함수를 보고 아래 실행되는 시점을 확인하고
위로 와서 함수를 보고 아래의 실행되는 시점을 확인하고
위로 와서 함수를 보고 아래의 실행되는 시점을 확인하고
위로 와서 함수를 보고 아래의 실행되는 시점을 확인하고
위로 와서 함수를 보고 아래의 실행되는 시점을 확인하고

하는 작업이 유지보수성 측면에서 가독성이 떨어져 휴먼에러를 발생시킬 수 있다.

2. Promise

promise 함수를 이용한 비동기 처리

콜백함수를 사용한 비동기처리와 비교하면,
순차적으로 실행되고, 가로로 길어지지도 않기 때문에 가독성 측면에서 좋다

프로미스 함수는 new 연산자와 함께 사용해야 한다.

new Promise(function(resolve, reject) {
  console.log('a')
  resolve('b'); // 이게 호출되면 .then이 실행 or 'b' 라는 인자를 전달
})
.then(function(result) { // result에 'b'를 받을수 있음
  console.log(result);
  return result='c';
})
.then(function(result) { // 처음의 result를 받는게 아니라 바로위의 result를 받음
  console.log(result); // c 출력
  return result='d';
})
.then(function(result) {
  console.log(result);
  return result='e';
})
.then(function(result) {
  console.log(result);
})
// a, b, c, d, e

new 연산자를 사용해서 Promise를 선언한다.
Promise 안에 콜백함수는 2개의 인자를 가진다.
(resolve, reject)
함수내부에서 resolve(첫번째 인자로 받아온 함수)가 호출되면 .then 메소드가 실행된다
(이때 resolve 함수에 인자로 전달하면 .then 메소드 내부의 함수가 받는다)

new Promise(function(resolve, reject) {
  console.log('a')
  reject('예외처리'); // 이게 호출되면 .catch가 실행 or '예외처리' 라는 인자를 전달
})
.then(function(result) {
  console.log(result);
  return result='c';
})
.catch(function(err) {
  console.log(err); // 예외처리
})
// a, 예외처리

함수 내부에서 reject(두번째 인자로 받아온 함수)가 호출되면 .catch 메소드가 실행된다
(이때 reject 함수에 인자로 전달하면 .catch 메소드 내부의 함수가 받는다)

3. async await

profile
제가 참고하기 위해 만든 블로그라 글을 편하게 작성했습니다. 틀린거 있다면 댓글 부탁드립니다.

0개의 댓글