[ Javascript ] 동기와 비동기

dayglow·2023년 11월 30일
0

Javascript

목록 보기
6/7
post-thumbnail

비동기

자바스크립트는 싱글스레드 입니다.
그래서 하나의 일을 할 때 하나밖에 못하는데 만약 그 하나의 일이 오래 걸리는 일이면
그 하나의 일이 끝날때 까지 다른 작업들은 기다려야합니다.
이러한 문제를 병렬로 해결하기 위해 존재하는 것이 비동기 입니다.

만약 비동기 요청이 여러개 있을 때 하나의 요청이 다른 요청의 결과에 의존한다면?

아래의 소스코드에서 처럼 둘 다 비동기 요청을 보내는데 두 번째 요청이 첫 번째 요청의 결과가 필요할 수가 있습니다. 하지만 둘 다 병렬적으로 요청을 보개기 때문에 response1을 가지기 전에 두 번째 요청이 보내지게 됩니다.

// 1st request
const response1 = request('http://abc.com');

// 2nd request
const response1 = request('http://abc.com', response1);

위와 같은 문제를 해결하는 세가지 방법

Callback 함수, Promise, Async Await 을 이용하는 세가지 방법이 있습니다.

콜백 함수

콜백 함수는 특정 함수에 매개변수로 전달된 함수를 의미합니다.
그리고 그 콜백함수는 함수를 전달받은 함수 안에서 호출됩니다.

function firstFunction(param, callback){
	const response1 = request(`http://`);
  	callback(response1);
}

function secondFunction(param, callback){
	const response2 = request(`http://`);
  	callback();
}

firstFunction(param, function (response1) {
	secondFunction(response1, function(){
    	thirdFunction(...)
    })
})

콜백 사용의 단점
1. 위에서 볼수 있듯이 소스 코드르 보는데 가독성이 떨어집니다.
2. 에러 처리를 한다면 모든 콜백에서 각각 에러 핸들링을 해주어야합니다.

Promise

Promise 객체는 new 키워드와 생성자를 사용해 만듭니다.
생성자는 매개변수로 실행함수를 받습니다.
이 함수는 매개 변수로 두 가지 함수를 받아야 하는데, 첫 번째 함수(resolve)는 비동기 작업을 성공적으로 완료해 결과를 값으로 반환할 때 호출해야 하고, 두 번째 함수(reject)는 작업이 실패하여 오류의 원인을 반환할 때 호출하면 됩니다.
두 번째 함수는 주로 오류 객체를 받습니다.

const myPromise = new Promise((resolve, reject) => {
  	// do something asynchronous which evnetually calls either: 
	//resolve(someValue); // fulfilled
  	//or
	//reject("failure reason"); // rejected
})

프로미스는 자바스크립트 비동기 처리에 사용되는 객체입니다.
Promise 객체는 비동기 작업이 맞이할 미래의 완료 또는 실패와 그 결과 값을 나타냅니다.

function fetchData(){
	return new Promise((resolve, reject) => {
    	const success = true;
      	if(success){
        	resolve('성공');
        }else{
        	reject('실패');
        }
    })
}

fetchData().then(function (result) {
	console.log('result',result); //성공
}).then(function (error) {
	console.log('error', error); //undefined
})

Promise는 다음 중 하나의 상태를 가집니다.
대기(pending) : 비동기 처리 로직이 아직 완료되지 않은 상태.
이행(fulfilled) : 비동기 처리가 완료되어 프로미스가 결과 값을 반환해준 상태.
거부(rejected) : 비동기 처리가 실패하거나 오류가 발생한 상태.

대기 중인 프로미스는 값과 함께 이행할 수도, 어떤 이유(오류)로 인해 거부될 수도 있습니다.
이행이나 거부될 때, 프로미스의 then 메서드에 의해 대기열(큐)에 추가된 처리기들이 호출됩니다.
이미 이행했거나 거부된 프로미스에 처리기를 연결해도 호출되므로, 비동기 연산과 처리기 연결 사이에 경합 조건은 없습니다.

Promise.all()

Promise.all() 메서드는 순회 가능한 객체에 주어진 모든 프로미스가 이행한 후,
혹은 프로미스가 주어지지 않았을 때 이행하는 Promise를 반환합니다.
주어진 프로미스 중 하나가 거부하는 경우, 첫 번째로 거절한 프로미스의 이유를 사용해 자신도 거부합니다.

const promise1 = Promise.resolve(3);
const promise2 = 42;
const promise3 = new Promise((resolve, reject) => {
	setTimeout(resolve, 3000, 'foo');
})

Promise.all([promise1, promise2, promise3]).then((values) => {
	console.log(values); // [3, 42, 'foo']
})

Promise.race()

Promise.race() 메서드는 Promise 객체를 반환합니다.
이 프로미스 객체는 Iterable 안에 있는 프로미스 중에 가장 먼저 완료된 것의 결과값으로 그대로 이행하거나 거부합니다.

const promise1 = new Promise((resolve, reject) => {
	setTimeout(resolve, 500, 'one');
})

const promise2 = new Promise((resolve, reject) => {
	setTimeout(resolve, 100, 'two');
})

Promise.race([promise1, promise2]).then((value) => {
	console.log(value); //two
})

Async Await

  • 비동기 코드를 마치 동기 코드처럼 사용할 수 있습니다.
  • Promise에 then메서드를 체인 형식으로 호출하는 것보다 가독성이 좋습니다.
  • await는 async 내부 함수에서만 사용할 수 있습니다.
  • 동기식 코드에서 쓰는 try... catch 구문을 async/await 구조에서 사용할 수 있습니다.

0개의 댓글