В моем предыдущем сообщении о блоге я объяснил основы генераторов в es6 JavaScript. Если вы не читали, вы можете проверить это здесь 👉 Понимание генераторов в es6 JavaScript
Многие из вас просили об использовании в реальном использовании генераторов, поэтому я собираюсь показать одну из проблем, с которыми я столкнулся.
Но чтобы объяснить проблему, я должен сказать несколько слов о нашем продукте Mews Navigator На что мы работаем.
Навигатор позволяет регистрировать онлайн, надежно хранить данные вашей кредитной карты и предоставлять вам полный контроль над информацией, которой вы хотите поделиться.
Так что теперь представьте, что вы выполняете онлайн-регистрацию через приложение, и вы переходите на шаг оплаты.
Поэтому, как только вы нажмете на следующую кнопку, вы увидите загрузчик, а затем список ваших платежных карт, довольно прямолинейный, верно?
Предоставление маршрута оплаты
На самом деле, это немного сложнее под капюшоном. Есть несколько шагов, которые необходимо решить до того, как компонент будет отображаться.
// 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 renderif not go to 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, которые приносят перед рендерингом компонент.
Уловка состоит в том, что если какая -либо из этих проверок может выйти из строя и основываясь на том, какие проверки снятся, мы перенаправляем в конкретный случай.
Итак, как решить это без использования внешних библиотек? Помните в прошлый раз, когда я показал вам этот пример?
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();
Просмотреть исходный код в коде и ящика
Посмотрите на возврат утверждение. Это остановит исполнение и проигнорирует все, что происходит после возврат утверждение.
Это может дать нам возможность итерации над обещаниями и отменить в любом месте в цепочке обещаний.
Доказательство концепции
Давайте создадим что -то достаточно для нашего варианта использования, чтобы решить этот случай в маршрутизации. Основными моментами были:
- Способен справляться с синхронизацией и асинхронными функциями (вызовы API)
- Код вернул перенаправление, как только некоторые проверки не сняты.
- Достаточно общего, чтобы мы могли повторно использовать и для других маршрутов.
Итак, я открыл кодовую песочницу и придумал это решение 👉 CodeSandbox
Как вы можете видеть в консоли, у нас есть несколько действий и некоторые проверки. Мы можем перемещаться по чеку, которая должна сбой, а остальная часть кода не выполняется.
Посмотреть исходный код в 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(() => )
)
};
Мне пришлось написать обработчик для нашего генератора. Это место, где магия случается. Я объяснил каждый шаг ниже в комментариях.
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());
};
Посмотреть исходный код в CodeSandbox
На данный момент я просто играю с этим, поэтому, если у вас есть представление о том, как решить это лучше, определенно дайте мне знать. 😉
Спасибо за чтение
Дайте мне знать в разделе комментариев, как вы относитесь к этому Серия генераторов . Если вам это нравится, вы знаете, что делать! Поделитесь этим со своими друзьями и коллегами.
Если вы хотите, чтобы я рассмотрел некоторые темы в следующем посте, DM здесь на dev.to или в Твиттере @phung_cz или, если у вас есть какие -либо предложения, не стесняйтесь комментировать ниже.
Увидимся в следующий раз и продолжайте взламывать ✌
Посмотрите на то, что мы строим @ Mews Systems мы тоже Наем разработчиков и люди на другие должности. DM, если у вас есть какие -либо вопросы.
Оригинал: “https://dev.to/tuanphungcz/canceling-promises-with-generators-in-es6-javascript-d01”