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상기 코드 실행 효 과 를 테스트 할 수 있 습 니 다.
더 많은 자 바스 크 립 트 관련 내용 은 본 사이트 의 주 제 를 볼 수 있 습 니 다.
본 고 에서 말 한 것 이 여러분 의 자 바스 크 립 트 프로 그래 밍 에 도움 이 되 기 를 바 랍 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Thymeleaf 의 일반 양식 제출 과 AJAX 제출텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.