본문 바로가기

WEB개발/JS&HTML

[JS] JS의 비동기 작업 ( = promise)

 비동기란 특정 코드의 연산이 끝날 때까지 코드의 실행이 끝나지 않은 상태에서, 순차적으로 다음 코드를 먼저 실행하는 JS의 특성이다. 요청에 대한 결과를 기다리지 않고 다음 코드를 실행한다는 것이다. 

 

  • 대기(pending): 이행하거나 거부되지 않은 초기 상태.
  • 이행(fulfilled): 연산이 성공적으로 완료됨.
  • 거부(rejected): 연산이 실패함.

 

function asyncTask(success) {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            if (success) {
                resolve("Task completed successfully!");
            } else {
                reject("Task failed!");
            }
        }, 2000); // 2초 후에 작업이 완료
    });
}

console.log("Task started...");

asyncTask(true)  // true를 전달하면 성공, false를 전달하면 실패
    .then(result => {
        console.log(result);  // 성공했을 때 실행
    })
    .catch(error => {
        console.error(error);  // 실패했을 때 실행
    })
    .finally(() => {
        console.log("Task finished");  // 성공 여부와 상관없이 실행
    });

 

  1. Pending (대기): 비동기 작업이 아직 완료되지 않은 상태.
  2. Fulfilled (성공): 비동기 작업이 성공적으로 완료된 상태.
  3. Rejected (실패): 비동기 작업이 실패한 상태.

 

이전까지 비동기화 작업은 주로 callback을 사용했다. 그러나 callback은 몇가지 문제가 있어 이를 보완하기 위해  promise가 등장합니다.

 

1. 비동기통신 응답 전달

  const get = url => {
	const xhr = new XMLHttpRequest() // XMLHttpRequest 객체생성
  xhr.open('GET', url) // HTTP요청 초기화
  xhr.send() // HTTP요청 전송
  
  xhr.onload = () => { // onload 이벤트 핸들러 프로퍼티에 바인딩하고 종료
    if (xhr.status === 200) {
      return xhr.response
    }
    console.error(`${xhr.status} ${xhr.statusText}`)
  }
}

const response = get('https://woo06.tistory.com/6')
console.log(response) // undefined

response를 반환하지만 undefinded인 이유는 응답을 받기 전에 이미 console.log가 수행되기 때문입니다.

 

Promise를 이용한 수정코드

const get = url => {
  return new Promise((resolve, reject) => {
    const xhr = new XMLHttpRequest(); // XMLHttpRequest 객체 생성
    xhr.open('GET', url); // HTTP 요청 초기화
    xhr.send(); // HTTP 요청 전송
    
    xhr.onload = () => { // onload 이벤트 핸들러 설정
      if (xhr.status === 200) {
        resolve(xhr.response); // 요청이 성공하면 resolve로 응답 반환
      } else {
        reject(new Error(`${xhr.status} ${xhr.statusText}`)); // 오류 발생 시 reject
      }
    };

    xhr.onerror = () => {
      reject(new Error('Request failed'));
    };
  });
};

get('https://woo06.tistory.com/6')
  .then(response => {
    console.log(response); // 응답이 성공적으로 도착하면 출력
  })
  .catch(error => {
    console.error('Error:', error); // 오류가 발생하면 출력
  });

 

 

2. 순차적 통신 수행

 

const get = (url, callback) => {
    const xhr = new XMLHttpRequest();
    xhr.open('GET', url);
    xhr.send();
    
    xhr.onload = () => {
      if (xhr.status === 200) {
        callback(null, xhr.response); // 성공적으로 데이터를 가져온 경우
      } else {
        callback(new Error(`${xhr.status} ${xhr.statusText}`), null); // 오류 발생
      }
    };
  
    xhr.onerror = () => {
      callback(new Error('Request failed'), null); // 요청 실패
    };
  };
  
  // 여러 데이터를 순차적으로 받는 코드 (콜백 방식)
  get('https://woo06.tistory.com/1', (error, response1) => {
    if (error) {
      return console.error('Error fetching first response:', error);
    }
    console.log('First response:', response1);
  
    get('https://woo06.tistory.com/2', (error, response2) => {
      if (error) {
        return console.error('Error fetching second response:', error);
      }
      console.log('Second response:', response2);
  
      get('https://woo06.tistory.com/3', (error, response3) => {
        if (error) {
          return console.error('Error fetching third response:', error);
        }
        console.log('Third response:', response3);
      });
    });
  });

 

Promise를 이용한 수정코드

const get = url => {
    return new Promise((resolve, reject) => {
      const xhr = new XMLHttpRequest();
      xhr.open('GET', url);
      xhr.send();
      
      xhr.onload = () => {
        if (xhr.status === 200) {
          resolve(xhr.response);
        } else {
          reject(new Error(`${xhr.status} ${xhr.statusText}`));
        }
      };
  
      xhr.onerror = () => {
        reject(new Error('Request failed'));
      };
    });
  };
  
  // 여러 데이터를 순차적으로 받는 코드 (async/await)
  const fetchSequentialData = async () => {
    try {
      const response1 = await get('https://woo06.tistory.com/1');
      console.log('First response:', response1);
  
      const response2 = await get('https://woo06.tistory.com/2');
      console.log('Second response:', response2);
  
      const response3 = await get('https://woo06.tistory.com/3');
      console.log('Third response:', response3);
    } catch (error) {
      console.error('Error:', error);
    }
  };
  
  fetchSequentialData(); // 순차적으로 데이터를 가져오는 함수 호출

 

 

 


 

https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Promise
 

Promise - JavaScript | MDN

Promise 객체는 비동기 작업이 맞이할 미래의 완료 또는 실패와 그 결과 값을 나타냅니다.

developer.mozilla.org

https://velog.io/@eunjin/JavaScript-Promise-%EB%93%B1%EC%9E%A5-%EB%B0%B0%EA%B2%BD-%EC%82%AC%EC%9A%A9%ED%95%98%EB%8A%94-%EC%9D%B4%EC%9C%A0-%EA%B8%B0%EB%B3%B8-%EB%A9%94%EC%84%9C%EB%93%9C-3%EA%B0%80%EC%A7%80-%EC%95%8C%EC%95%84%EB%B3%B4%EA%B8%B0

 

[JavaScript] 비동기 처리의 의미, 콜백 패턴의 문제점, Promise의 등장 배경

기능 구현만을 위해 백엔드 데이터를 받아오기 위해 기계적으로 썼던 fetch, then 등 자바스크립트의 비동기 처리를 위한 문법을 다시 들여다보고 기본을 다잡고자 정리해보려 한다. 프로미스란

velog.io

 

 

'WEB개발 > JS&HTML' 카테고리의 다른 글

[JS] Async, Await, Fetch, PromiseAll  (0) 2023.03.06
[JS, JAVA] 정규식  (0) 2022.06.13
[JS] Engine, Event Loop  (0) 2021.06.24
[html] input(inputmode, event, pattern)  (0) 2021.06.24
[JS] JavaScript 유용한 Array 함수  (0) 2021.06.23