Конвертировать будущее будущего в сказочный результат

У меня есть следующий пример кода для получения 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 функция.

Вы можете позвонить, чтобы сигнализировать Будущему, что вы больше не заинтересованы в конечном результате, позволяя Будущему навести порядок.


Вместо этого вы можете сделать две вещи:

  1. Не конвертируйте свое будущее в результат, а вместо этого конвертируйте результаты в фьючерсы. Фьючерсы - это надмножества Результата. Они представляют успех и неудачу, а также асинхронность и ввод / вывод. Поскольку ваша программа асинхронна, и вы не можете заблокировать поток в Node, вы, скорее всего, в конечном итоге получите Future в качестве основного типа на краю своей программы (аналогично тому, как вы в конечном итоге получаете async функция в точке входа, когда вы используете обещания).
  2. Предоставьте оставшуюся часть вашей программы в обратном вызове. Вы уже 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
Другие вопросы по тегам