ES6 Javascript에서 생성기로 약속 취소
많은 분들이 제너레이터의 실제 사용 사례를 요청하셨기 때문에 제가 직면한 문제 중 하나를 보여드리겠습니다.
소개
그러나 문제를 설명하기 위해 우리가 작업 중인 Mews Navigator 제품에 대해 몇 마디 말해야 합니다.
The Navigator allows you to check-in online, securely storing your credit card details and giving you full control over the information that you want to share.
이제 앱을 통해 온라인 체크인을 하고 결제 단계를 진행한다고 상상해 보세요.
따라서 다음 버튼을 클릭하면 로더와 결제 카드 목록이 표시됩니다. 아주 간단하죠?
지불 경로 렌더링
실제로 내부는 좀 더 복잡합니다. 구성 요소를 렌더링하기 전에 해결해야 할 몇 가지 단계가 있습니다.
// Let's say user goes to this url:
// www.mews.li/navigator/check-in/payment/:reservationId
// 1. This will check if the user is signed in.
// If yes go render <Dashboard /> if not go to <SignIn />
authAction(); // async
// 2. We need to fetch the reservations
fetchReservations(); // async
// 3. We need to check if `reservationId` and
// route itself is valid (If all checks pass go to next one)
isReservationIdValid({ reservations, currentReservation }); // sync
// 4. Fetch paymentcards
fetchPaymentCards(); // async
// 5. Fetching hotel entitites
fetchHotels(); // async
// 6. Some of hotels uses PCI proxy vault, if it does,
// we need to initialize PCI proxy script.
doesHotelUsePciProxy({ hotels, hotelId }); // sync
// 7. Fetch and init the script
initPciProxy(); // async
구성 요소를 렌더링하기 전에 몇 가지 검사와 일부 API 가져오기가 있습니다.
The catch is that if any of these checks could fail and based on which checks to fail, we would redirect to a specific case.
그렇다면 외부 라이브러리를 사용하지 않고 이 문제를 해결하는 방법은 무엇일까요? 저번에 이거 보여줬던 거 기억나?
function* avengersGenerator() {
yield "Hulk"; // Pausing the execution
yield "Thor";
yield "Iron man";
return "Ultron"; // Exiting of finishing the generator
yield "Spiderman";
}
const iterator = avengersGenerator();
iterator.next();
View source code in codesandbox
return
문을 살펴보십시오. 이렇게 하면 실행이 중지되고 return
문 뒤에 있는 모든 내용이 무시됩니다.
이를 통해 Promise를 반복하고 Promise Chain의 어느 곳에서나 취소할 수 있습니다.
개념의 증거
라우팅에서 이 사례를 해결하기 위해 사용 사례에 대해 충분히 일반적인 것을 만들어 봅시다. 요점은 다음과 같습니다.
The Navigator allows you to check-in online, securely storing your credit card details and giving you full control over the information that you want to share.
// Let's say user goes to this url:
// www.mews.li/navigator/check-in/payment/:reservationId
// 1. This will check if the user is signed in.
// If yes go render <Dashboard /> if not go to <SignIn />
authAction(); // async
// 2. We need to fetch the reservations
fetchReservations(); // async
// 3. We need to check if `reservationId` and
// route itself is valid (If all checks pass go to next one)
isReservationIdValid({ reservations, currentReservation }); // sync
// 4. Fetch paymentcards
fetchPaymentCards(); // async
// 5. Fetching hotel entitites
fetchHotels(); // async
// 6. Some of hotels uses PCI proxy vault, if it does,
// we need to initialize PCI proxy script.
doesHotelUsePciProxy({ hotels, hotelId }); // sync
// 7. Fetch and init the script
initPciProxy(); // async
The catch is that if any of these checks could fail and based on which checks to fail, we would redirect to a specific case.
function* avengersGenerator() {
yield "Hulk"; // Pausing the execution
yield "Thor";
yield "Iron man";
return "Ultron"; // Exiting of finishing the generator
yield "Spiderman";
}
const iterator = avengersGenerator();
iterator.next();
그래서 코드 샌드박스를 열었고 이 해결책을 제시했습니다 👉 Codesandbox
콘솔에서 볼 수 있듯이 여러 작업과 몇 가지 검사가 있습니다. 실패할 것으로 예상되는 검사와 나머지 코드가 실행되지 않는 부분을 이동할 수 있습니다.
View the source code in codesandbox
그리고 다음은 코드의 결제 단계 경로에 대한 구현 예입니다.
function* paymentRouteGenerator() {
yield authAction();
yield fetchReservations();
yield isReservationIdValid();
yield fetchPaymentCards();
yield fetchHotels();
yield doesHotelUsePciProxy({ hotelId });
yield initPciProxy();
}
const CHECK_IN_PAYMENT_ROUTE = {
name: Route.CheckInPayment,
path: "/:reservationId",
action: resolveAction(
generatorWrapper(paymentRouteGenerator),
renderComponent(() => <CheckInPaymentStep />)
)
};
생성기용 핸들러를 작성해야 했습니다. 이것은
magic
가 발생하는 곳입니다. 댓글에서 아래의 모든 단계를 설명했습니다.const generatorWrapper = generator => context => {
// 1. Creating an iterator
const iterator = generator(context);
// 3. This function except yielded as a argument
const handle = yielded => {
const handleWithRedirectCheck = route => {
// 4. Here is where the magic happens, we check if there is a redirect, if yes,
// it would redirect (cancel) and will not execute the rest of the generator
if (get("redirect", route)) {
return route;
}
// Otherwise continue
return handle(iterator.next());
};
// Exit if we are at the end of the generator
if (yielded.done) {
return;
}
// Handling the async case if action/check is a promise
if (isPromise(yielded.value)) {
return yielded.value.then(handleWithRedirectCheck);
}
// If its not a promise, we can call handleWithRedirectCheck directly
return handleWithRedirectCheck(yielded.value);
};
// 2. Handling the iterator
return handle(iterator.next());
};
View the source code in codesandbox
지금은 그냥 가지고 노는 것이므로 더 좋은 방법으로 이 문제를 해결하는 방법을 알고 있다면 반드시 알려주세요. 😉
읽어 주셔서 감사합니다
이 발전기 시리즈에 대해 어떻게 생각하는지 의견 섹션에서 알려주십시오. 당신이 그것을 사랑한다면, 당신은 무엇을 해야할지 압니다! 친구 및 동료와 공유하십시오.
다음 게시물에서 몇 가지 주제를 다루기를 원하시면 여기 또는 트위터에서 저에게 DM을 보내거나 제안 사항이 있으면 아래에 댓글을 달아주세요.
다음에 또 뵙고 계속 해킹하세요✌
우리가 무엇을 만들고 있는지@ Mews systems 우리는 또한hiring devs 다른 위치에 있는 사람들을 살펴보십시오. 질문이 있으시면 DM 주세요.
Reference
이 문제에 관하여(ES6 Javascript에서 생성기로 약속 취소), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/tuanphungcz/canceling-promises-with-generators-in-es6-javascript-d01텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)