3

我有以下示例代码来获取 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
4

2 回答 2

2

将 Future 转换为同步数据结构是不可能的,因为它必须阻塞线程。获得 Future 结果的唯一方法是提供回调。

在以下行中:

const result = future.fold(Result.Error, Result.Ok).fork(x => x, x => x)

您已经假设您提供的回调fork的返回值将确定整个表达式的返回值,因此被分配给result常量。

当然,问题是这些回调最终会在异步工作完成时在稍后的 JavaScript 滴答声中被调用。这意味着在其中一个回调运行时,该result变量将早已被分配并且可能也被读取。

相反,fork返回一个unsubscribe函数。因此,您分配的实际值result就是该unsubscribe函数。

您可以调用它来向 Future 发出信号,表明您不再对最终结果感兴趣,从而允许 Future 进行清理。


你可以做两件事:

  1. 不要将您的 Future 转换为 Result,而是将 Results 转换为 Futures。期货是结果的超集。它们代表成功和失败,以及异步和 I/O。由于您的程序是异步的,并且您不能阻塞 Node 中的线程,因此您很可能最终会在程序的边缘将 Future 作为您的主要类型(类似于您最终async在入口点使用函数时你正在使用 Promises)。
  2. 在回调中提供程序的其余部分。您已经fold将拒绝分支编辑到Result类型中,因此您可以安全地使用valuefrom Fluture 来提供单个回调:

    future.fold(Result.Error, Result.Ok).value(result => result.map(...))
    
于 2018-07-25T11:16:13.780 回答
2

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
于 2018-07-19T12:48:10.567 回答