Зачем будущее народных сказок?
Фон
Я читаю каждый дюйм документации и пытаюсь узнать о Folktale как можно больше. Недавно я решил попробовать Future
,
Нужно ли нам будущее?
Теперь пока я понимаю разницу между Task
а также Promise
и между Task
а также Future
(поддержка отмены) мне не понятна разница между Future
а также Promise
,
Почему я хотел бы использовать Future
вместо Promise
? Какие преимущества я бы получил? Ну, вы можете сказать: "Таким образом, у вас действительно есть монада, а не извините за монаду".
И это хороший аргумент сам по себе, но... имея в виду, мне всегда нужно переходить от Обещания к чему-то другому (к будущему), и что Future
API почти такой же, мне, как кому-то новому, непонятно, почему я должен заботиться о Future
совсем.
Пример кода
Предположим, у меня есть эта функция, где request
это функция, которая делает запрос и возвращает некоторые результаты.
extractRequestInfo
это функция, которая извлекает данные из объекта ответа. Если что-то не получается, я catch
ошибка и вернуть объект со всеми данными, badId и ошибкой.
const requestFruit = request => data =>
request( data )
.then( extractRequestInfo )
.catch( error => ( { badId: prop( [ "Id" ], data ), error } ) );
Учитывая, что это HTTP-запрос, я знаю, что мне не нужен Task
потому что нет отмены, я могу сделать здесь. Так что мои варианты Promise
а также Future
,
Вопросы
- Как бы я использовал
Future
в этом образце? - Так как это то, что может потерпеть неудачу, я должен использовать
Result
также?
1 ответ
Цитирую ответ от создателя Quil:
Будущее решает ту же проблему, что и Promise, поэтому концептуальных различий между ними нет. Разница в том, как они решают проблему.
Обещания могут быть выполнены успешно или не выполнены. При любом преобразовании, которое вы применяете к значению обещания, ошибки, генерируемые синхронно, будут неявно перехватываться, а также отклонять обещание. Это интересно в async / await, потому что вы можете обрабатывать эти ошибки (синхронные и асинхронные) аналогичным образом - вам не нужно превращать каждую синхронную операцию в обещание, потому что среда выполнения сделает это за вас.
Недостатком этого является то, что очень легко отлавливать ошибки, которые вы не собирались делать, и заставить вашу систему работать в несовместимом состоянии. Я не думаю, что вы можете многое сделать со статическим анализом здесь тоже.
У фьючерсов нет этой проблемы, потому что ничто не скрыто в будущем. Если вы хотите, чтобы синхронные операции использовали конвейер Future для обработки ошибок, вы должны явно указать их там. Это дает вам больший контроль над обработкой ошибок, а неперехваченные ошибки все равно будут приводить к аварийному завершению процесса (как ожидается, избегая запуска вашей программы в несовместимых состояниях памяти для случаев, которые вы не предсказывали), но для написания программ таким способом требуется больше усилий.
Кроме этого, если вы рассматриваете Задачи, Futures моделирует конечное значение Задачи со случаем успеха, случаем отказа и случаем отмены. Обещания имеют только случай успеха и случай сбоя, поэтому отмена моделируется как специальное значение сбоя. Это немного меняет идиомы для обработки отмен. Для кода, использующего обещания, возможно обрабатывать сбои, не зная об этом специальном значении отмены, что может быть проблемой, так как это значение может легко быть потеряно во время этих преобразований.
В кодовых базах, которые смешивают обещания и задачи, эти проблемы более сложны, потому что неявное снятие ошибок, которые делают обещания, не очень совместимо с явным снятием ошибок, которые ожидают задачи / будущее (это может привести к таким проблемам: #163). Найти эти ошибки становится намного сложнее, чем если бы у вас были только обещания или только задачи / фьючерсы. Не уверен, что лучший способ справиться с этими случаями еще.
Для оригинального обсуждения: