Конвертировать будущее будущего в сказочный результат
У меня есть следующий пример кода для получения 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
}
)
Результат не является сопоставляемым типом и выдает ошибку, когда я вызываю result.map
:
TypeError: result.map is not a function
2 ответа
Невозможно преобразовать Future в синхронную структуру данных, так как он должен был бы блокировать поток. Единственный способ получить результат в будущем - это предоставить обратный вызов.
В следующей строке:
const result = future.fold(Result.Error, Result.Ok).fork(x => x, x => x)
Вы сделали предположение, что возвращаемое значение обратных вызовов, которые вы предоставили fork
будет определять возвращаемое значение всего выражения, и, следовательно, будет назначен result
постоянная.
Проблема, конечно же, заключается в том, что эти обратные вызовы будут вызываться в конце концов, в какой-нибудь более поздней версии JavaScript, когда будет выполнена асинхронная работа. Это означает, что к моменту запуска одного из обратных вызовов result
Переменная будет давно назначена и, вероятно, также прочитана.
Вместо, fork
возвращает unsubscribe
функция. Таким образом, фактическое значение, которое вы присвоили result
в том, что unsubscribe
функция.
Вы можете позвонить, чтобы сигнализировать Будущему, что вы больше не заинтересованы в конечном результате, позволяя Будущему навести порядок.
Вместо этого вы можете сделать две вещи:
- Не конвертируйте свое будущее в результат, а вместо этого конвертируйте результаты в фьючерсы. Фьючерсы - это надмножества Результата. Они представляют успех и неудачу, а также асинхронность и ввод / вывод. Поскольку ваша программа асинхронна, и вы не можете заблокировать поток в Node, вы, скорее всего, в конечном итоге получите Future в качестве основного типа на краю своей программы (аналогично тому, как вы в конечном итоге получаете
async
функция в точке входа, когда вы используете обещания). Предоставьте оставшуюся часть вашей программы в обратном вызове. Вы уже
fold
отклонил ветку отклонения вResult
типа, так что вы можете безопасно использоватьvalue
от Fluture, чтобы обеспечить один обратный вызов:future.fold(Result.Error, Result.Ok).value(result => result.map(...))
fork
выполняет будущее и ожидает, что вы обработаете результаты в обратных вызовах, которые вы предоставили в fork
аргументы, и что более важно, возвращает cancel
функция, а не следующая Future
как вы ожидаете моего заявления .map
на его результат.
Измените код на:
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