Рубрики
Без рубрики

Как создать питонский декоратор в JavaScript

Автор оригинала: FreeCodeCapm Team.

Сэм Гализия

В этой статье я хочу показать вам, как я создал функцию декоратора для питона в JavaScript и, в процессе, показывать хотя бы одно практическое использование.

В конце я хочу продемонстрировать, как я использовал это, чтобы решить более углубленную проблему, и, возможно, вдохновляет некоторых из вас, чтобы сделать то же самое!

Начиная

Давайте начнем с быстрого повышения квалификации (или урока) на декораторы в Python. В Python есть функции, называемые декораторами, которые следуют за этим синтаксисом, @decorator Отказ

В коде их последуют следующую функцию, подобную так:

Приведенный выше фрагмент кода использует синтаксическую сахарующую версию использования декораторов в Python. Чтобы лучше понять, что происходит здесь, давайте удалим этот синтаксический сахар.

На этом втором фрагменте мы смотрим на определение декоратора и о том, как мы украсим функцию без синтаксического сахара.

Одним из важнейших моментов, которые нужно убрать из этого, в том, что декоратор просто обернут нашу оригинальную функцию внутри функции обертки и вызывая его.

Используя эту технику упаковки нашей функции, мы можем выполнять задачи до и после прогонов нашей функции. Давайте взглянем на использование случая, которое будет пролить более света на то, как это все работает.

Создание нашего декоратора

Мы собираемся создать графический декоратор, который скажет нам, как долго требуется функция для запуска.

В декоратере Timing мы начинаем, отметив текущее время и экономя его начну. Затем мы выполняем оригинальную функцию, и после того, как закончилось, отметьте текущее время в конце. Наконец мы возвращаем разницу между началом и временем окончания, по сути, давая нам время, чтобы запускать функцию.

Этот простой корпус использования – это только верхушка айсберга, когда дело доходит до декораторов. Прежде чем мы пойдем больше глубины с использованием случаев, я хочу показать, насколько легко достичь того же результата в JavaScript.

То, что вы видите выше, – это тот же грамотор, который мы сделали в Python, но написанные в JavaScript. Я хочу выделить несколько небольших изменений синтаксиса, которые различаются образуют версию Python.

Во-первых, внутри нашей функции декоратора мы используем анонимные функции в JavaScript. Использование анонимной функции также позволяет нам вернуть его при определении его.

Во-вторых, мы также использовали анонимную функцию в синтаксисе экспрессии функции в строке 10. Мы передаем анонимную функцию как аргумент для Сроки вместо того, чтобы использовать именованную функцию.

Это незначительные синтаксические различия на языке и, надеемся, не будут отключить вас слишком много, если вы не знакомы с ними.

Дайвинг глубже

Теперь, когда мы смотрели на простой пример, я хочу пойти на некоторую глубину на более полезный случай. В процессе мы собираемся выйти через проблему, в которую я столкнулся, когда решил продолжить это решение.

Это проблема с двумя деталями, поэтому давайте посмотрим на первую часть: неспособность сетевых звонков.

При работе с API вы, несомненно, найдуте себя с сетевыми звонками, которые не потерпели неудачу по любому количеству причин. Не было бы неплохо, если бы у нас могли бы эти сети звонить, повторите попытку?

Ну, это просто так бывает, что вы можете! В следующем фрагменте мы создадим декоратор в JavaScript, который будет использовать NPM-библиотеку, которая называется повторением, чтобы сделать это.

* На боковом примечании полностью можно написать повторный код самостоятельно. Я решил использовать библиотеку, чтобы сделать вещи немного проще, так как это не фокус этой статьи.

Хорошо, это было много, чтобы принять! Я пытался комментировать части, чтобы помочь объяснить, что происходит, но давайте сломаемся пошаговым шагом.

Во-первых, нам требуется библиотека повторных попыток, которые можно найти здесь и продолжить создание нашей функции декоратора.

Внутри нашего декоратора первое, что мы хотим сделать, это создать операцию. Операции являются частью библиотеки повторных попыток и обозначают, что у нас есть то, что мы хотим сделать, это может потребовать более одной попытки.

В настройке операции вы можете увидеть, я установил {Повтор: 2} Отказ Варианты могут быть переданы в конструктор операции в качестве объекта, содержащего опцию CONFIG, вы хотите изменить. Настройка Повторные потенды Как вы можете указать максимальное количество попыток.

Библиотека Retry имеет немного конфигурации, которую вы сможете использовать, чтобы настроить, как ваши попытки повторных попыток, но я не хочу получать отслеживаемую стороной. Проверьте NPM Библиотека Узнать больше!

Далее мы настроим нашу анонимную функцию, которая будет обернуть нашу оригинальную функцию. Вы, возможно, были немного запутаны, когда вы посмотрели на строку 9, const; Отказ Я знаю, что я путался этим, когда я впервые увидел это, так что позвольте мне объяснить.

В основном, так как мы называем завернутый Далее внутри функции в более низком объеме мы должны прихватывать аргументы от него сейчас, чтобы мы могли получить доступ к ним позже. Ключевое слово . Аргументы Прихватывает аргументы из текущей функции в качестве массива. Мы храним текущий Аргументы в args позволяя нам использовать его позже.

Следующая часть – это то, где все начинают становиться немного запутанным. Я использую сетевую библиотеку, которая возвращает обещания, и из-за этого нам нужно перехватить обещание внутри декоратора. Перехватывание Это позволяет нам проверить, преуспевает ли это или потерпел неудачу, а затем сделать что-то об этом.

Ниже приведена только внутренняя часть нашей функции упаковки декоратора.

Чтобы перехватить ответ от сетевого вызова, мы завершаем нашу работу (которая содержит нашу функцию, которую мы хотим повторить) внутри другого обещания. Для тех из вас, кто ранее использовал обещания, я знаю, что это может быть странным, но нужно, чтобы убедиться, что мы обрабатываем результат этого звонка здесь. Это будет еще более очевидно, почему, когда я покажу свой последний пример, так что оставайтесь настроенными!

Двигаясь, теперь, когда мы завернули или оригинальную функцию и операцию повторите попытку внутри обещания, мы можем на самом деле позвонить завернутый Отказ Когда мы называть это, нам нужно, чтобы он был надо использовать Применить (контекст, args ...) так что наши исходные параметры, переданные ему, могут быть использованы.

После того, как мы получим ответ от нашего сетевого звонка, мы обрабатываем случай успеха и ошибки. Здесь добится скучный случай успеха: в основном, если мы получим успешный ответ, мы решим внешнее обещание с результатом.

Чехол ошибки гораздо интереснее! Если запрос не удается, мы хотим попробовать снова верно? Этот фрагмент, if (apption.retry (err)) {return; } Интересно, потому что это сердце библиотеки повторных попыток. Мы в основном пытаемся вызвать функцию снова. При этом мы передаем текущую ошибку в функцию повторения.

Операция имеет внутреннюю массив ошибок, а вызывание повторной попытки с ошибкой нажимает эту ошибку на массив, а затем снова вызывает операцию. Вот почему мы должны были вызвать нашу оригинальную функцию внутри Операция. Потрясающий () Отказ

Сначала я был немного запутанным по возвращаться; Заявление внутри брекетов. То, что я узнал, играя с этим, это то, что после звонка Повторите попытку () Функция должна вернуть так, чтобы Операция можно выполнить снова. В противном случае без возврата он застрял в исполнении и не удалось с неразрешенным обещанием.

Окончательный интересный кусок в вышеуказанном коде – это когда мы не можем сделать еще одну попытку – то есть мы только что выполнили нашу последнюю попытку. В этом случае, если заявление, если вы не пройдете, когда вы пытаетесь позвонить Повторите попытку () И мы обходим этот блок к финальному разделу, где мы Отклонить (Err) Отказ Это очень важно, потому что если вы не включите эту окончательную обработку ошибок, внешнее обещание никогда не будет разрешено.

Последний кусок головоломки

Ух ты, это было много, чтобы объяснить, и я уверен, что это было много, чтобы принять. Я хочу показать вам один последний фрагмент, хотя, прямо из моей кодовой базы, что показывает, как я использую эту функциональность, чтобы иметь дело с истекшими токенами во время сетевых звонков. Отказ

Быстрая Backstory: я работаю с API Spotify API, а их токены Authens находятся только в течение 60 минут. Из-за короткого срока службы я обнаружил, что не должен часто освежать во время развития. Понимая, что это может быть реальной проблемой для пользователей, я подумал, как мы решили эту проблему во время стажировки, которую я сделал.

Мой предыдущий опыт с аналогичной ситуацией (в SWIFT на iOS) привел меня к написанию этого последнего куска кода здесь. Я проверил это, и это работает удивительно! Пользователь, вероятно, даже никогда не узнает, что их токен истек, что это должно быть, может я добавить.

В приведенной выше функции есть много путей разветвленного кода, и большинство из него не новое. Я сделал все возможное, чтобы объяснить всю логику в комментариях. Я использую этот код и проверил это много раз, и токен обновляется, и ответ возвращается как ожидалось!

Ниже приведен краткое использование случая того, как я использую эту функцию после записи его.

Мне очень понравилось писать эту статью, и я хотел бы услышать некоторые отзывы от тех, кто чувствует себя до него. Код выше, вероятно, может быть дополнительно оптимизирован каким-то образом, но это то, что я в настоящее время использую, и он работает:)

Я надеюсь, что это помогло хотя бы одного человека решить подобную проблему. Если так, я хотел бы услышать, как вы использовали это!