Reputation: 6642
I have the following sample code to fetch a uuid:
const Result = require('folktale/result')
const Future = require('fluture')
Future.prototype.flatMap = Future.prototype.chain
const fetch = Future.encaseP(require('node-fetch'))
const message = err => `ERROR: ${err.message}`
function getUuid () {
return fetch('https://httpbin.org/uuid')
}
const future = getUuid()
.map(response => {
const responseJson = response.json.bind(response)
const getResponseBody = Future.encaseP(responseJson)
return getResponseBody()
})
.map(obj => obj.uuid)
const result = future.fold(Result.Error, Result.Ok).fork(x => x, x => x)
console.log(result) // [Function: Sequence$cancel]
result.map(
x => {
return message(x)
},
x => {
console.log(x)
return x
}
)
The result is not a mappable type and throws an error when I invoke result.map
:
TypeError: result.map is not a function
Upvotes: 3
Views: 439
Reputation: 3031
It is impossible to convert a Future to a synchronous data structure, as it would have to block the thread. The only way to get at the result of a Future is to provide a callback.
In the following line:
const result = future.fold(Result.Error, Result.Ok).fork(x => x, x => x)
You've made the assumption that the return value of the callbacks you've provided to fork
would determine the return value of the entire expression, and therefore be assigned to the result
constant.
The problem, of course, is that these callbacks will be called eventually, in some later JavaScript tick, when the asynchronous work is done. This means that by the time one of the callbacks runs, the result
variable will have long been assigned and probably also read.
Instead, fork
returns an unsubscribe
function. So the actual value you've assigned to result
is that unsubscribe
function.
You can call it to signal to the Future that you're no longer interested in the eventual result, allowing the Future to clean up.
There are two things you might do instead:
async
function at the entry point when you're using Promises).Provide the remainder of your program inside the callback. You've already fold
ed the rejection branch away into the Result
type, so you can safely use value
from Fluture to provide a single callback:
future.fold(Result.Error, Result.Ok).value(result => result.map(...))
Upvotes: 3
Reputation: 1991
fork
executes future and expects that you handle results in callbacks you've provided in fork
arguments, and more importantly returns cancel
function, not next Future
as you expect my applying .map
on its result.
Change the code to:
const cancelToken = future
.fold(Result.Error, Result.Ok)
// if you wanna map result, do it here:
// .map(...)
.fork( // fork consumes the fluture and ends execution chain
ok => message(x),
err => { console.log(err); }
);
// call cancelToken() if you want to cancel it
Upvotes: 2