В проблеме с обещаниями в JavaScript я посмотрел на то, как API и дизайн обещаний ощущались случайно опасны для написания ответственного и безопасного кода.
Я включен раздел Предлагая библиотеку ( Fpromise ), которые использовали функциональный подход для преодоления этих проблем.
После того, как он был опубликован, Майк Шеров Был достаточно добрый, чтобы ответить на твит о статье и предложил его взять на него: что я недооценил ценность синтаксиса ASYNC/ASYNC (что он подвергается хитрым тогда/поймать API и возвращает нас к «нормальному» поток) И что проблемы, которые остаются (т. Е. Плохое обращение с ошибками), являются проблемами с самим JavaScript (который TC39 всегда развивается).
Я очень благодарен за свои мысли об этом, и помогая выяснить контр-рассказ к тому, который я предложил !!
Вот что говорит Майк:
Давайте посмотрим на пример статьи статьи:
const handleSave = async rawUserData => { try { const user = await saveUser(rawUserData); createToast(`User ${displayName(user)} has been created`); } catch { createToast(`User could not be saved`)); } };
Я преследовал это, так как попытка была «поймана» слишком много, и использовала точку, что если DisplayName
бросил, пользователь будет предупрежден, что ни один пользователь не был сохранен, даже если это было. Но – хотя код немного монотонный – это преодолено – и было плохим разобщенным, чтобы не показывать.
Если наш улов умный о обработке ошибок, это уходит.
const handleSave = async rawUserData => { try { const user = await saveUser(rawUserData); createToast(`User ${displayName(user)} has been created`); } catch (err) { if (err instanceof HTTPError) { createToast(`User could not be saved`)); } else { throw err; } } };
И если эволюция языка включает в себя лучшую обработку ошибок, этот подход будет чувствовать себя лучше:
// (code includes fictitious catch handling by error type) const handleSave = async rawUserData => { try { const user = await saveUser(rawUserData); createToast(`User ${displayName(user)} has been created`); } catch (HTTPError as err) { createToast(`User could not be saved`)); } };
Хотя это намного лучше, я до сих пор белкнул о слишком многом в попытке. Я верю, что поймать Должен Только уловить за исключением, что они намерены (плохая работа из меня в оригинальном посте), но в том, что объем того, что «пробовала», должно быть максимально минимально.
В противном случае, поскольку код растет, есть столкновения пойманы:
// (code includes fictitious catch handling by error type) const handleSave = async rawUserData => { try { const user = await saveUser(rawUserData); createToast(`User ${displayName(user)} has been created`); const mailChimpId = await postUserToMailChimp(user); } catch (HTTPError as err) { createToast(`Um...`)); } };
Так вот более узкий подход о том, что мы ловим:
// (code includes fictitious catch handling by error type) const handleSave = async rawUserData => { try { const user = await saveUser(rawUserData); createToast(`User ${displayName(user)} has been created`); try { const mailChimpId = await postUserToMailChimp(user); createToast(`User ${displayName(user)} has been subscribed`); } catch (HTTPError as err) { createToast(`User could not be subscribed to mailing list`)); } } catch (HTTPError as err) { createToast(`User could not be saved`)); } };
Но теперь мы находимся в блоке попробовать/ловить «ад». Давайте попробуем выйти из этого:
// (code includes fictitious catch handling by error type) const handleSave = async rawUserData => { let user; try { user = await saveUser(rawUserData); } catch (HTTPError as err) { createToast(`User could not be saved`)); } if (!user) { return; } createToast(`User ${displayName(user)} has been created`); let mailChimpId; try { await postUserToMailChimp(rawUserData); } catch (HTTPError as err) { createToast(`User could not be subscribed to mailing list`)); } if (!mailChimpId) { return; } createToast(`User ${displayName(user)} has been subscribed`); };
Несмотря на то, что это ответственный и безопасный код, он чувствует себя самым нечитаемым и, как мы делаем что-то не так и уродливую и работаю в гору против языка. Кроме того, помните, что этот код использует сжатый фиксирующий обработчик ошибок, а не еще более подробный (реальный) код проверки типа ошибки и обрабатывающую его еще раз.
Который (я верю) Точно так же, что обращение с ошибками (в целом) нуждается в улучшении, и именно моя точка зрения – что выполнение Async Code с обещаниями небрежно опасно, так как он делает опасный код чистым и эргономичным, а ответственный код менее читаемый и интуитивно понятный.
Итак, как это может быть лучше? Что если бы было –
Ждать укладки
Что если бы мы могли сделать что-то вроде этого?
// (code includes fictitious await catch handling by error type) const handleSave = async rawUserData => { const [user, httpError] = await saveUser(rawUserData) | HTTPError; if (httpError) { return createToast(`User could not be saved`)); } createToast(`User ${displayName(user)} has been created`); const [id, httpError] = await saveUser(rawUserData) | HTTPError; if (httpError) { return createToast(`User could not be subscribed to mailing list`)); } createToast(`User ${displayName(user)} has been subscribed`); };
Это хорошо читает и безопасно и ответственно! Мы ловим точно, чтобы тип ошибки мы намереваемся. Любая другая ошибка вызывает ждать “бросить”.
И он может быть использован с несколькими типами ошибок. Например,
// (code includes fictitious catch handling by error type) const [user, foo, bar] = await saveUser(rawUserData) | FooError, BarThing;
Насколько близко мы можем добраться до этого в пользовательской плате?
Довольно близко. Представляем Fawait (как в функционале – ждут).
const {fa} = require('fawait'); const [user, httpError] = await fa(saveUser(rawUserData), HTTPError); const [user, foo, bar] = await fa(saveUser(rawUserData), FooError, BarThing);
Спасибо за прочтение!
Крейгмичаэльмартин/Fawait.
Библиотека JavaScript для получения более функциональной
Установка
npm install --save fawait
Что такое Fawait?
Fawait
Является ли библиотека JavaScript для работы с ждать
синтаксис для обещаний.
Оберните свое обещание в ФА
Функция и предоставить ошибки, которые вы хотите поймать, и вы получите массив, вы можете распаковать к этим значениям. Любые ошибки не указаны, будут брошены.
Читайте об этом: зарабатывание больше функционала в JavaScript
let [data, typeError, customBadThing] = await fa(promise, TypeError, BadThing);
Альтернативы/предшествующее искусство
FPROMISE
который является более тяжелым решением обещания.Go-for-It
иБезопасный-ждут
которые преобразуют все нерутивные ошибки в эту функциональную форму.ждать до js
который преобразует все ошибки в эту функциональную форму.
Оригинал: “https://dev.to/craigmichaelmartin/making-await-more-functional-in-javascript-2le4”