본문 바로가기
JavaScript

[JavaScript] 비동기

by lvd-hy 2023. 5. 4.
반응형

JavaScript는 동기적 언어이다. 

동기(synchronous)

JavaScript는 싱글 스레드 기반으로 동작하는 언어로 특정 코드의 실행이 완료될 때까지 기다리고 난 후 다음 코드를 수행하는 한다.

컴퓨터 발전에 따라 하나의 컴퓨터가 여러 작업을 처리하는 등의 기능이 필요하게 되었다. → 비동기식이 필요하다.(ex.유튜브, 게임 등)

비동기(asynchronous)

특정 코드의 실행이 완료될 때까지 기다리지않고 다음 코드들을 수행하는 것

 

JavaScript 비동기적 실행(Asynchronous execution)

아래 작업의 경우 비동기적 실행으로 작동되어야 효율적이다.

  • 백그라운드 실행, 로딩 창 등의 작업
  • 인터넷에서 서버로 요청을 보내고, 응답을 기다리는 작업
  • 큰 용량의 파일을 로딩하는 작업

비동기 경험

타이머 관련 API

setTimeout(function, delay, arg) : 일정 시간 후에 함수를 실행

// 예시 1 : callback를 사용하여 setTimeout 실행
// setTimeout (callback, millisecond)
setTimeout(function () {
  console.log('1초 후 실행');
}, 1000);
// 123 (임의의 타이머 ID)

// 예시 2 : callback 함수를 화살표함수 형태로 사용하여 setTimeout 실행
setTimeout( ()=> {
	console.log('1초 후 실행');
}, 1000);
// 17 (임의의 타이머 ID)

// 예시 3 : 함수명을 이용하여 setTimeout 실행
function timer() {
	console.log('1초 후 실행');
}
let timerLet = (setTimeout(timer, 1000));
// undefined
// 1초 후 실행

// 예시 4 : 함수와 인자를 이용하여 setTimeout함수를 실행
function result (name, age) {
	console.log (`이름은 ${name} 입니다.`);
	console.log (`나이는 ${age}살 입니다.`);
}
let timerlet = setTimeout(result, 1000, "김코딩", "23");
// undefined
// 이름은 김코딩 입니다.
// 나이는 23살 입니다.

clearTimeout(timeoutID) : setTimeout 타이머를 종료

const timer = setTimeout(function () {
  console.log('10초 후 실행'); // console에 출력되지않음(10초 후 실행할 것을 취소했기 때문)
}, 10000);
clearTimeout(timer);
// return 값: 없음
// setTimeout이 종료됨.

setInterval(function, delay, arg) : 일정 시간의 간격을 가지고 함수를 반복적으로 실행

// 예시 1 : callback를 사용하여 setTimeout 실행
// setTimeout (callback, millisecond)
setInterval(function () {
  console.log('1초마다 실행');
}, 1000);
// 123 (임의의 타이머 ID)

clearInterval(intervalID) : setInterval 타이머를 종료

const timer = setInterval(function () {
  console.log('1초마다 실행');
}, 1000);
clearInterval(timer);
// return 값: 없음
// setInterval이 종료됨.

clearTimeout 이 setInterval 를 종료할 수 있고, clearInterval 이 setTimeout 를 종료할 수 있다.
단, 명확성과 혼란 방지를 위하여 아래와 같이 사용할 것
setTimeout은 clearTimeout과 사용
setInterval은 clearInterval과 사용

 

비동기 코드는 실행할 때마다 순서가 바뀜

예시

const printString = (string) => {
  setTimeout(function () {
    console.log(string);
  }, Math.floor(Math.random() * 100) + 1);
};

const printAll = () => {
  printString('A');
  printString('B');
  printString('C');
};

printAll();

console.log(`아래와 같이 비동기 코드는 순서를 보장하지 않습니다!`);

// 터미널
아래와 같이 비동기 코드는 순서를 보장하지 않습니다!
C
B
A

비동기 코드 제어하기

1. Callback 함수 사용

const printString = (string, callback) => {
  setTimeout(function () {
    console.log(string);
    callback();
  }, Math.floor(Math.random() * 100) + 1);
};

const printAll = () => {
  printString('A', () => {
    printString('B', () => {
      printString('C', () => {});
    });
  });
};

// 터미널
아래와 같이 Callback 함수를 통해 비동기 코드의 순서를 제어할 수 있습니다!
A
B
C

2. Promise, asyns/await

Callback 함수로 제어할 수 있지만 코드가 길어지고 복잡해진다.

가독성이 낮아지는 Callback Hell이 발생하는 단점이 있다.

Promise는 Callback Hell을 방지하며, 비동기 코드를 제어할 수 있다.

Promise

new Promise : Promise는 class이기 때문에 new 키워드로 Promise 객체 생성

Promise 는 비동기 처리를 수행할 콜백 함수(executor)를 인수로 전달받는데 이 콜백 함수는 resolve , reject 함수를 인수로 전달받음

let promise = new Promise((resolve, reject) => {
	resolve(value);
	reject(error);
})

Promise 객체의 내부 프로퍼티 State : 기본 상태 pending (대기), 성공 fulfilled (이행), 에러 rejected (거부) Result : 처음 undefined , 성공 value , 에러 error

 

then, catch, finally

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

promise
.then(value => {
	console.log(value);
	// "성공"
})
.catch(error => {
	console.log(error);
})
.finally(() => {
	console.log("성공이든 실패든 작동!");
	// "성공이든 실패든 작동!"
})

Promise chaining : 비동기 작업을 순차적으로 진행할 때 사용

// 예시 1
const printString = (string) => {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve();
      console.log(string);
    }, Math.floor(Math.random() * 100) + 1);
  });
};

const printAll = () => {
  printString('A')
    .then(() => {
      return printString('B');
    })
    .then(() => {
      return printString('C');
    });
};

printAll();

console.log(
  `아래와 같이 Promise를 통해 비동기 코드의 순서를 제어할 수 있습니다!`
);

// 출력
아래와 같이 Promise를 통해 비동기 코드의 순서를 제어할 수 있습니다!
A
B
C

// 예시 2
let promise = new Promise(function (resolve, reject) {
  resolve('성공');
  // reject("실패");
});

promise
  .then((value) => {
    console.log(value);
    return '성공';
  })
  .then((value) => {
    console.log(value);
    return '성공';
  })
  .then((value) => {
    console.log(value);
    return '성공';
  })
  .catch((error) => {
    console.log(error);
    return '실패';
  })
  .finally(() => {
    console.log('성공이든 실패든 작동!');
  });

// 출력
성공
성공
성공
성공이든 실패든 작동!

Promise.all() : 여러 개의 비동기 작업을 동시에 처리할 때 (Promise chaining 보다 처리 속도 빨라짐)

// 기존
const result = [];
promiseOne()
  .then(value => {
    result.push(value);
    return promiseTwo();
  })
  .then(value => {
    result.push(value);
    return promiseThree();
  })
  .then(value => {
    result.push(value);
   console.log(result);  
	 // ['1초', '2초', '3초']
  })

// promise.all
Promise.all([promiseOne(), promiseTwo(), promiseThree()])
  .then((value) => console.log(value))
  // ['1초', '2초', '3초']
  .catch((err) => console.log(err));

// promise.all은 Promise 중 하나라도 에러 발생 시 나머지 Promise의 state와 상관없이 즉시 종료
Promise.all([
	new Promise((resolve, reject) => setTimeout(() => reject(new Error('에러1'))), 1000),
	new Promise((resolve, reject) => setTimeout(() => reject(new Error('에러2'))), 2000),
	new Promise((resolve, reject) => setTimeout(() => reject(new Error('에러3'))), 3000),
])
	.then((value) => console.log(value))
  .catch((err) => console.log(err));
	// Error: 에러1

Async/Await : Promise 코드를 간결하게 작성

// 함수 선언식
async function funcDeclarations() {
	await 작성하고자 하는 코드
	...
}

// 함수 표현식
const funcExpression = async function () {
	await 작성하고자 하는 코드
	...
}

// 화살표 함수
const ArrowFunc = async () => {
	await 작성하고자 하는 코드
	...
}

// 예시
const printString = (string) => {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve();
      console.log(string);
    }, Math.floor(Math.random() * 100) + 1);
  });
};

const printAll = async () => {
  await printString('A');
  await printString('B');
  await printString('C');
};

printAll();

console.log(
  `Async/Await을 통해 Promise를 간결한 코드로 작성할 수 있게 되었습니다.`
);
반응형

'JavaScript' 카테고리의 다른 글

redux  (0) 2023.04.24
[JavaScript] 함수선언식, 함수표현식, 화살표함수  (0) 2023.03.26
[JavaScript] 배열, 배열 메서드(method)  (0) 2023.03.25
[JavaScript] 타이머 API  (0) 2023.03.19
[JavaScript] 배열 고차 함수  (0) 2023.03.17

댓글