TIL: Javascript | async await / blocking / non-blocking - 221105

Lumpen·2022년 11월 7일
0

TIL

목록 보기
183/244

async / await

callback - promise - async/await
발전된 자바스크립트 비동기 처리 문법

async 로 지정한 함수는 항상 promise 를 반환한다
명시적으로 promise를 반환할 수 있지만 그러지 않아도 결과는 같다

await 는 async 로 지정된 함수 내부에서만 동작하며
내부적으로 .then() 이 동작하는 것과 같은 것으로
async 로 지정된 함수 중간에 비동기 호출의 then() 을 변수처럼 다룰 수 있는 것이다

thenable 객체를 받을 수 있다
promise 객체와 마찬가지로 async await 문법은 thenable한 객체를 받을 수 있다
객체 내부에서 참조할 수 있는 then() 메소드가 있고, resolve, reject를 받아서 사용하도록 정의한다면 thenable한 객체로 평가하여 사용 가능하다

blocking / non-blocking

자바스크립트는 asyncronous / non-blocking 으로 동작한다
blocking/non-blocking 의 경우 한 작업이 다른 작업을 호출 시
바로 return 하는지에 따라 나뉜다

non-blocking 이란 코드의 실행 완료 여부와 관계 없이 return 하여 다른 코드의 실행을 막지 않는다는 뜻이다
blocking 은 완료 시 까지 return을 하지 않고 막는다는 뜻..

코드의 실행이 다른 코드의 실행을 막을 수 있다는 것은
제어권으로 표현할 수 있다

자바스크립트의 경우 싱글 스레드이기 때문에 하나의 작업 흐름이 있고
하나의 제어권을 갖는다
이 제어권을 일반 함수에서는 순차적으로 가져가서 사용하고 반납하는데
blocking의 경우 함수의 실행이 완료될 때 까지 반납을 하지 않고 다른 코드의 실행을 막는다
non-blocking의 경우 실행 여부와 관계 없이 반납하여 원래의 작업 흐름을 바로 이어갈 수 있다

동기의 경우 완료 시점에 대해 기다리기 때문에 blocking으로 제어권을 바로 반환하지 않아도
행동에 대한 예측이 쉽다
non-blocking을 하게 되면 제어권을 바로 반납받기 때문에 기존의 작업을 수행하면서
제어권을 가져갔던 함수의 완료 여부에 대해 지속적으로 확인한다

비동기의 경우 호출한 함수가 호출된 함수의 완료 여부를 기다리진 않지만 blocking을 한다면 제어권을 돌려받지 못하여 동기 처럼 동작한다
non-blocking을 한다면 제어권을 바로 돌려받기 때문에 기존의 완료 여부를 기다리지 않고 기존의 동작을 수행하는 것으로 예측이 쉽다
대신 비동기 함수는 완료 시점에 콜백을 반환하여 task queue로 보내고 이벤트 루프를 통해 기존 실행 흐름인 call stack 이 비어있을 때 콜백 함수를 call stack으로 보내 실행하는 것으로 작업의 완료 여부를 확인할 수 있다

https://steady-coding.tistory.com/531

aysnc / await 는 blocking..?

async / await 는 block 으로 이해하는 경우가 많다
await 가 순서를 보장하기 때문이다

async 로 지정된 함수 내부에서
await 끼리 blocking을 하는 것 처럼 보이게 동작하기 때문이다

하지만 await 는 .then() 을 변수 내부에 저장하여 보류했다가 순서대로 실행할 뿐이기 때문에
blocking 을 한다고 보기에는 어렵다

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function

async await 문법은
async 로 지정된 함수 내부에서만 await 으로 담은 비동기 호출이
동기 처럼 순서를 보장하는 것일 뿐 blocking 이라고 볼 수 없다

async 로 작성된 함수가 자신을 호출한 기존 작업 흐름에 대해 제어권을 거의 바로 받납하기 때문이다

await는 해당 라인에서 Promise가 resolve될 때까지 함수의 실행을 일시 중지,
하지만 이는 해당 함수 내부에서만의 블로킹으로, 전체 프로그램이나 이벤트 루프는 계속 실행된다

async function foo() {
  console.log("hi");
  return 1; 
}

async function bar() {
  const result = await foo();
  console.log(result);
}

bar();
console.log("lo"); 

hi - lo - 1 순서로 실행 결과를 얻을 수 있다

만약 async await 가 blocking 으로 동작한다면
hi - 1 - lo 의 순서의 결과를 반환해야 한다

https://ko.javascript.info/async-await

1. 동기 블로킹 (Synchronous Blocking):

  • 작업이 순차적으로 실행, 현재 작업이 완료될 때까지 다음 작업을 수행하지 않는다
    다른 작업을 실행하지 못하고 대기하는 상태가 된다
function sleep(ms) {
  const wakeUpTime = Date.now() + ms;
  while (Date.now() < wakeUpTime) {}
}

console.log("시작");
sleep(2000); // 2초 동안 블로킹
console.log("2초 후");
// "시작" 출력 후 2초 뒤에 "2초 후" 출력

2. 동기 논블로킹 (Synchronous Non-blocking):

  • JavaScript에서는 흔하지 않은 패턴
  • 작업을 요청한 후 즉시 제어권을 반환받지만, 작업 완료 여부를 주기적으로 확인
  • 작업 결과를 동기적으로 받지만, 그 과정에서 다른 작업을 수행할 수 있다
// 폴링을 통한 동기 논블로킹 구현 예시
function waitForCondition(condition) {
    while (!condition()) {
        // 다른 작업을 수행할 수 있음
        console.log("대기 중...");
        // 짧은 시간 동안 대기
        setTimeout(() => {}, 100);
    }
    return true;
}

// 실제 사용 예시
let isReady = false;
setTimeout(() => { isReady = true; }, 2000);

console.log("시작");
const result = waitForCondition(() => isReady);
console.log("완료:", result);

3. 비동기 블로킹 (Asynchronous Blocking):

  • JavaScript에서는 드문 패턴이지만, 특정 상황에서 발생할 수 있다
  • 비동기적으로 작업을 시작하지만, 결과를 기다리는 동안 다른 작업을 수행하지 못한다
// 함수는 비동기지만, CPU를 블록함
async function processData() {
    console.log("시작");
    const result = await heavyComputation(); // CPU가 블록됨
    console.log("결과:", result);
}

// CPU 집약적 작업
async function heavyComputation() {
    return new Promise(resolve => {
        // 복잡한 계산 작업
        let result = 0;
        for(let i = 0; i < 1000000000; i++) {
            result += Math.random();
        }
        resolve(result);
    });
}

4. 비동기 논블로킹 (Asynchronous Non-blocking):

가장 일반적인 JavaScript 패턴

  • 작업을 요청하고 즉시 다음 작업으로 넘어간다
  • 작업이 완료되면 콜백, Promise, 또는 async/await를 통해 결과를 처리한다
console.log("시작");

fetch("https://api.example.com/data")
  .then(response => response.json())
  .then(data => console.log("데이터:", data))
  .catch(error => console.error("에러:", error));

console.log("요청 보냄");
// "시작", "요청 보냄"이 먼저 출력되고, 
// API 응답이 오면 "데이터: ..." 가 출력됨
profile
떠돌이 생활을 하는. 실업자, 부랑 생활을 하는

0개의 댓글