javascript 함수 의 일시 정지 및 복구 인 스 턴 스 상세 설명

이 실례 는 자 바스 크 립 트 함수 의 일시 정지 와 복 구 를 설명 한다.여러분 께 참고 하도록 공유 하 겠 습 니 다.구체 적 으로 는 다음 과 같 습 니 다.
javascript 비동기 프로 그래 밍 은 항상 어 려 운 문제 입 니 다.처음에 우 리 는 callback 을 사 용 했 지만 이에 따라 지옥 으로 되 돌아 가'발명'Promise 는 callback 이 너무 깊 은 문 제 를 해결 하 였 습 니 다.그러나 Promise(일련의 then)를 남용 하여 코드 를 읽 기 가 쉽 지 않 게 되 었 다.이때,async-await 가 하늘 로 날 아 올 랐 습 니 다.동기 화 된 방식 으로 비동기 코드 를 만 들 수 있 게 해 주 었 습 니 다.정말 놀 랍 습 니 다.그래서 어떤 사람들 은 이것 이 자바 script 비동기 프로 그래 밍 의 은 탄 이 라 고 말 할 수 있 습 니 다.
P.S.코드 는 프 리 젠 테 이 션 일 뿐 사용 할 수 없습니다.

function getProfile(id) {
 return window.fetch(`https://api.com/wedding/profile/${weddingId}`
}

async function getWeddingDetail(weddingId) {
 try {
  //     
  const wedding = await window.fetch(`https://api.com/wedding/${weddingId}`);
  //          ,      
  const groom = await getProfile(wedding.groomId);
  // ...      ->    ...
  const bride = await getProfile(wedding.brideId);
  // ...     
  return { wedding, bride, groom };
 } catch (error) {
  handleError(error);
 }
}

은 탄 이 없다
그러나 컴퓨터 과학 분야 에는 은 탄 이 존재 하지 않 는 다.async-await 도 단점 이 있 습 니 다.예 를 들 어 당신 은 await 를 쓰 는 것 을 잊 었 습 니 다.믿 지 않 습 니까?
다른 사람 이 getProfile 이라는 도구 함 수 를 만 들 었 다 고 가정 합 니 다.구체 적 인 실현 을 모 르 면 동기 함수 로 생각 하 시 겠 습 니까?getProfile 이 비동기 적 이 더 라 도.
물론,이것 은 작은 문제 일 뿐 입 니 다.더욱 힘 든 것 은,만약 당신 이 한 함수 에서 async 를 사용 했다 면,그것 을 호출 하 는 함수 도 하나의 async 가 되 어야 합 니 다.만약 또 다른 함수 가 이 호출 함 수 를 호출 하려 면...holly shit!이제 알 겠 지?
쌍방 이 모두 좋게 할 방법 이 있 습 니까?

// getWeddingDetail               or  
function getWeddingDetail(weddingId) {
 const wedding = window.fetch(`https://api.com/wedding/${weddingId}`);
 const groom = getProfile(wedding.groomId);
 const bride = getProfile(wedding.brideId);
 return { wedding, bride, groom };
}

중간 에 해결 할 수 없 는 것 은 아무것도 없다.
비동기 프로 그래 밍 의 핵심 은 함수 일시 정지 와 복구 입 니 다.그리고 함수 가 일시 정지 인지 재 개 인지 결정 합 니 다.이것 은 js 가 실 행 될 때 하 는 일 입 니 다.우리 가 오늘 엔진 에 깊이 들 어가 서 실현 해 야 합 니까?
No!나 는 C++를 모 르 고 js 엔진 이 어떻게 실현 되 었 는 지 모른다.
그러나 저 는 중간 층(함수 runtime)을 써 서 위의 수 요 를 실현 하려 고 할 수 있 습 니 다.물론 제한 이 있 을 수 있 습 니 다.
입구 함수
실행 할 함수 가 다음 과 같다 고 가정 합 니 다.

function main() {
 const id = 123;
 console.log('Getting wedding:', id);

 const { wedding, bride, groom } = getWeddingDetail(id);

 console.log('Wedding detail:', wedding);
}

우 리 는 아래 의 방식 에 따라 운행 할 수 있 기 를 기대한다.

function runtime(mainFn) {
 mainFn();
}

// start runtime
runtime(main);

기본 틀 이 이미 있 는데 이어서 무엇 을 합 니까?
우선,await 를 사용 하지 않 는 전제 에서 함수 운행 을 어떻게 중단 하 는 지 알 아야 합 니 다.
그리고 적당 한 곳 에서 집행 을 재개한다.
js 에 서 는 함수 운행 을 중단 하 는 두 가지 방법 이 있 습 니 다:return 과 throw.이상 으로 인 한 중단 을 표시 하기 때문에 throw 를 선택 하 겠 습 니 다.자,우리 runtime 개조 합 시다.

function runtime(mainFn) {
 const _originalFetch = window.fetch;
 window.fetch = (url, options) => {
  // "  "
  throw new Error();
 };
 //       
 runMain();

 function runMain() {
  try {
   mainFn();
  } catch (error) {
   //    "  "
   //         mainFn
   runMain();
  }
 }
}

먼저 이 코드 에 나타 난 문 제 를 무시 하고 함수'중단','복구'라 는 두 가지 점 에 시선 을 모 으 면 목적 이 이미 달성 되 었 음 이 분명 합 니 다.다음은 그것 을 최적화 시킨다.
첫 번 째 는 runMain 입 니 다.window.fetch 가 성공 한 후에 실행 해 야 합 니 다.

function runtime(mainFn) {
 const _originalFetch = window.fetch
 window.fetch = (url, options) => {
  _originalFetch(url, options).then(res => {
   //          
   runMain()
  })
  throw new Error()
 }

 runMain();

 function runMain() {
  try {
   mainFn();
  } catch (error) {
   // ignore
  }
 }
}

window.fetch 가 매번 이상 을 던 질 때마다 mainFn 이 무한 순환 으로 실 행 됩 니 다.
이 문 제 를 해결 하려 면 캐 시 를 도입 해 야 합 니 다.첫 번 째 fetch 에서 이상 을 던 지고 뒤의 요청 에 응답 을 되 돌려 야 합 니 다.

function runtime(mainFn) {
 const _originalFetch = window.fetch
 windo.fetch = (url, options) => {
  if (cache.has([url, options])) return cache.get([url, options])

  _originalFetch(url, options).then(res => {
   cache.set([url, options], res)
   runMain()
  })

  throw new Error()
 }

 runMain();

 function runMain() {
  try {
   mainFn();
  } catch (error) {
   // ignore
  }
 }
}

성 공 했 어!
프로그램 을 실행 하고 console 의 출력 을 검사 합 니 다.여러 번 반복 되 었 기 때문에'Getting wedding:', 123도 여러 번 표시 되 었 습 니 다.이것 은 console.log 의 부작용 으로 인 한 것 입 니 다.
순 함수
runtime 은 순수 함수 만 실행 할 수 있 습 니 다.코드 에 부작용 이 있 으 면 제한 조건 을 추가 해 야 합 니 다:runSideEffects().

function main() {
 const id = 123;
 runSideEffects(() => console.log('Getting wedding:', id));

 const { wedding, bride, groom } = getWeddingDetail(id);

 runSideEffects(() => console.log('Wedding detail:', wedding));
}

sideEffects 의 실현 은 매우 쉽다.

function runtime(mainFn) {
 //        

 //    `runSideEffects`
 const sideEffects = [];
 window.runSideEffects = fn => {
  sideEffects.push(fn);
 };

 runMain();

 function runMain() {
  try {
   mainFn();
   sideEffects.forEach(fn => fn());
  } catch (error) {
   //      
   sideEffects.splice(0, sideEffects.length);
  }
 }
 
}

다시 실행,'Getting wedding:', 123한 번 만 표 시 됩 니 다~
도대체 뭘 한 거 야?
함수 일시 정지 와 복 구 를 모방 하기 위해 서,우 리 는 throw 의 오 류 를 통 해'일시 정지'함 수 를 다시 실행 하여'복구'함 수 를 다시 실행 합 니 다.
일시 정지 에서'복구'하기 위해 서 는 던 진 오 류 를 함수 반환 값 으로 교체 해 야 합 니 다.우 리 는 캐 시 시스템 으로 이 목적 을 달성 하 였 습 니 다.
마지막 으로 함 수 를 안전하게 반복 할 수 있 도록 순 함수 로 바 꿔 야 합 니 다.부작용 이 있 으 면 모 아서 함수 가 실 행 된 후에 부작용 을 수행 합 니 다.
이렇게 많아
본 논문 의 영감 은React Suspense에서 나온다.Suspense 가 있 으 면 아래 와 같이 데 이 터 를 가 져 올 수 있 습 니 다.

function Component() {
 const data = getDataFromNetwork();
 return <div />;
}
getDataFromNetwork 에서 비동기 요청 을 할 것 이기 때문에 비동기 함수 이지 만 React 는 동기 화 작업 으로 보 입 니 다.이거 재 밌 다~
원문 읽 기:pause-and-resume-a-javascript-function
관심 있 는 친 구 는 온라인 HTML/CSS/JavaScript 코드 실행 도 구 를 사용 할 수 있 습 니 다.http://tools.jb51.net/code/HtmlJsRun상기 코드 실행 효 과 를 테스트 할 수 있 습 니 다.
더 많은 자 바스 크 립 트 관련 내용 은 본 사이트 의 주 제 를 볼 수 있 습 니 다.
본 고 에서 말 한 것 이 여러분 의 자 바스 크 립 트 프로 그래 밍 에 도움 이 되 기 를 바 랍 니 다.

좋은 웹페이지 즐겨찾기