AsyncContext

왜 필요할까? - 문제 1. 비동기에서의 맥락 상실

// 동기 코드 - 문제 없음
function processUser() {
  const userId = getCurrentUser(); // hope
  
  logAction(); // hope 이 무언가를 함
  saveData();   // hope의 데이터 저장
}

// 비동기 코드
async function processUser() {
  const userId = getCurrentUser(); // hope
  
  await delay(100);
  
  logAction();  // 누가 한 건지 모름
  saveData();   // 누구 데이터인지 모름!
}

왜 사라질까?

let currentUser = null;

async function handleRequest(user) {
  currentUser = user;  // "hope" 저장
  
  await fetchData();   // 다른 요청이 들어오면?
  // 이 사이에 다른 요청: currentUser = "someone"
  
  console.log(currentUser);  // "someone"이 출력됨
}

// 동시에 두 요청
handleRequest("hope");
handleRequest("someone");

문제 2. React 에서 실제로 겪는 문제

function SubmitButton() {
  const [isPending, startTransition] = useTransition();
  
  const handleClick = () => {
    console.log('클릭!', isPending);  // false
    
    startTransition(async () => {
      console.log('시작', isPending);  // true 
      
      await api.submit();
      
      console.log('API 후', isPending);  // ??? 
      // 여기가 문제. 리액트는 이게 같은 transition인지 모름
      
      navigate('/success');
      
      console.log('navigate 후', isPending);  
    });
  };
  
  return <button disabled={isPending}>제출</button>;
}

어떻게 AsyncContext 가 사용될까?

// 1. AsyncContext 생성
const userContext = new AsyncContext.Variable();

// 2. 값 설정하고 비동기 작업 실행
async function handleRequest(userId) {
  await userContext.run(userId, async () => {
    // 이 안의 모든 비동기 작업에서 userId 접근 가능
    
    await step1();
    await step2();
    
    setTimeout(() => {
      console.log(userContext.get());  // userId 출력!
    }, 1000);
  });
}

// 3. 어디서든 값 가져오기
async function step1() {
  const userId = userContext.get();  // Hope
  await saveLog(userId);
}

async function step2() {
  const userId = userContext.get();  // Hope
  await updateData(userId);
}

어떻게 동작하는가?

실제로 비슷한 개념 (node.js 의 Async Local Storage https://nodejs.org/api/async_context.html#class-asynclocalstorage)