Folktale 的未来是什么?
What is Folktale's Future for?
背景
我正在阅读文档的每一寸内容,并尽可能多地了解 Folktale。
最近,我决定尝试 Future
.
我们需要未来吗?
虽然我了解 Task
和 Promise
之间以及 Task
和 Future
之间的区别(支持取消),但我不清楚两者之间的区别Future
和 Promise
。
为什么我要使用 Future
而不是 Promise
?我会有什么好处?
好吧,你可以说:"This way you actually have a monad, instead of a sorry excuse for a monad".
这本身就是一个很好的论点,但是...考虑到我总是需要将 Promise 转换为其他东西(到 future )并且 Future
的 API几乎是一样的,作为一个新手,我不清楚为什么我应该关心 Future
。
代码示例
假设我有这个函数,其中 request
是一个发出请求和 return 一些结果的函数。
extractRequestInfo
是一个从响应对象中提取数据的函数。
如果出现故障,我 catch
错误和 return 一个包含所有数据、badId 和错误的对象。
const requestFruit = request => data =>
request( data )
.then( extractRequestInfo )
.catch( error => ( { badId: prop( [ "Id" ], data ), error } ) );
鉴于这是一个 HTTP 请求,我知道我不需要 Task
因为我无法在此处执行取消操作。所以我的选择是 Promise
和 Future
.
问题
- 如何在此示例中使用
Future
?
- 因为这可能会失败,我是否也应该使用
Result
?
引用创作者Quil的回复:
Future solves the same problem Promise does, so there isn't much of a
conceptual difference between the two. The difference is more in how
they solve the problem.
Promises can either settle successfully or fail. In any transformation
you apply to a promise's value, errors thrown synchronously will be
implicitly caught and reject the promise as well. This is interesting
in async/await because you can handle these errors (synchronous and
asynchronous) in a similar way--you don't need to lift every
synchronous operation into a promise, because the runtime will do that
for you.
The downside of this is that it's very easy to catch errors that you
didn't intend to, and have your system run in an inconsistent state. I
don't think you can do much with static analysis here either.
Futures don't have that problem because nothing is lifted into a
future implicitly. If you want synchronous operations to use the
Future pipeline for handling errors, you have to put them there
explicitly. This gives you more control over error handling, and
uncaught errors will still crash the process as expected (avoiding
having your program run into inconsistent memory states for cases you
didn't predict), but it takes more effort to write programs this way.
Other than that, if you consider Tasks, Futures model the eventual
value of a Task with a success case, a failure case, and a
cancellation case. Promises only have a success case and a failure
case, so cancellation is modelled as a special failure value. This
changes the idioms for handling cancellations a bit. It's possible for
code using promises to handle failures without being aware of this
special cancellation value, which may be a problem since this value
may easily be lost during these transformations.
In codebases that mix promises and tasks, these problems are more
complicated because the implicit-lifting of errors that promises do is
not very compatible with the explicit-lifiting of errors that
tasks/futures expect (this can lead to problems like this one: #163).
Finding these bugs becomes a lot harder than if you had only promises
or only tasks/futures. Not sure what's the best way to handle these
cases yet.
原讨论:
背景
我正在阅读文档的每一寸内容,并尽可能多地了解 Folktale。
最近,我决定尝试 Future
.
我们需要未来吗?
虽然我了解 Task
和 Promise
之间以及 Task
和 Future
之间的区别(支持取消),但我不清楚两者之间的区别Future
和 Promise
。
为什么我要使用 Future
而不是 Promise
?我会有什么好处?
好吧,你可以说:"This way you actually have a monad, instead of a sorry excuse for a monad".
这本身就是一个很好的论点,但是...考虑到我总是需要将 Promise 转换为其他东西(到 future )并且 Future
的 API几乎是一样的,作为一个新手,我不清楚为什么我应该关心 Future
。
代码示例
假设我有这个函数,其中 request
是一个发出请求和 return 一些结果的函数。
extractRequestInfo
是一个从响应对象中提取数据的函数。
如果出现故障,我 catch
错误和 return 一个包含所有数据、badId 和错误的对象。
const requestFruit = request => data =>
request( data )
.then( extractRequestInfo )
.catch( error => ( { badId: prop( [ "Id" ], data ), error } ) );
鉴于这是一个 HTTP 请求,我知道我不需要 Task
因为我无法在此处执行取消操作。所以我的选择是 Promise
和 Future
.
问题
- 如何在此示例中使用
Future
? - 因为这可能会失败,我是否也应该使用
Result
?
引用创作者Quil的回复:
Future solves the same problem Promise does, so there isn't much of a conceptual difference between the two. The difference is more in how they solve the problem.
Promises can either settle successfully or fail. In any transformation you apply to a promise's value, errors thrown synchronously will be implicitly caught and reject the promise as well. This is interesting in async/await because you can handle these errors (synchronous and asynchronous) in a similar way--you don't need to lift every synchronous operation into a promise, because the runtime will do that for you.
The downside of this is that it's very easy to catch errors that you didn't intend to, and have your system run in an inconsistent state. I don't think you can do much with static analysis here either.
Futures don't have that problem because nothing is lifted into a future implicitly. If you want synchronous operations to use the Future pipeline for handling errors, you have to put them there explicitly. This gives you more control over error handling, and uncaught errors will still crash the process as expected (avoiding having your program run into inconsistent memory states for cases you didn't predict), but it takes more effort to write programs this way.
Other than that, if you consider Tasks, Futures model the eventual value of a Task with a success case, a failure case, and a cancellation case. Promises only have a success case and a failure case, so cancellation is modelled as a special failure value. This changes the idioms for handling cancellations a bit. It's possible for code using promises to handle failures without being aware of this special cancellation value, which may be a problem since this value may easily be lost during these transformations.
In codebases that mix promises and tasks, these problems are more complicated because the implicit-lifting of errors that promises do is not very compatible with the explicit-lifiting of errors that tasks/futures expect (this can lead to problems like this one: #163). Finding these bugs becomes a lot harder than if you had only promises or only tasks/futures. Not sure what's the best way to handle these cases yet.
原讨论: