Конвертировать будущее будущего в сказочный результат - PullRequest
0 голосов
/ 16 мая 2018

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

0 голосов
/ 25 июля 2018

Невозможно преобразовать 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(...))
    
0 голосов
/ 19 июля 2018

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
...