在 Ramda 中有条件地承诺

Conditional with promise in Ramda

如何使用 R.cond 和 promise?

像这样..

const fetchBin = (url) => fetch(`https://httpbin.org${url}`).then((response) => {
    var contentType = response.headers.get("content-type");
    if(contentType && contentType.includes("application/json")) {
      return response.json();
    }
    throw new TypeError("Oops, we haven't got JSON!");
})

const testStatus = (status) => fetchBin(`/status/${status}`);

const isOk = R.propEq('statusCode', 200);
const testCond = R.cond([
    [ R.pipeP(testStatus, isOk), (resp) => console.log('The resp is ', resp) ],
    [ R.T, (code) => console.log('The resp is NOT ok', code) ]
])

testCond(404)
// R.pipeP(testStatus, isOk)(404)
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.24.1/ramda.min.js"></script>

我认为这就是您所追求的,通过将其与 testStatus 组合,您应该能够获得 response 对象并进行条件分支。

const fetchBin = (url) => fetch(`https://httpbin.org${url}`).then((response) => {
    var contentType = response.headers.get("content-type");
    if(contentType && contentType.includes("application/json")) {
      return response.json();
    }
    throw new TypeError("Oops, we haven't got JSON!");
})

const testStatus = (status) => fetchBin(`/status/${status}`);

const isOk = R.propEq('statusCode', 200);
const testCond = R.pipeP(testStatus, R.cond([
  [isOk, resp => console.log('The resp is OK :' + resp.statusCode)],
  [R.T, resp => console.log('The resp is NOT OK :' + resp.statusCode)]
]));

testCond(404)
// R.pipeP(testStatus, isOk)(404)
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.24.1/ramda.min.js"></script>

全新视角

it's good to remind ourselves that we should be the ones bending our programming languages, not the other way around

我觉得你走错了路。 fetchBin 是我们真正要找的人中的稻草人。我们需要一个接受 URL 和 returns 解析后的 JSON 响应的函数;让我们称这个人为fetchJSON

从那里,我们使用 fetchJSON 实现 fetchBin – 资源 returns 是 404 状态还是 200 状态并不重要使用错误的内容类型(参见下面的 XML 示例)——无论哪种方式,promise 都将被正确地路由到错误处理程序(下面的 console.error;或者 .then(console.log).catch(console.error))——这里的重点,如果我不清楚,是 fetchBin 不应该关心诸如 HTTP 状态代码是什么或响应的 Content-Type header 之类的细节——让它要求解析 JSON,不用担心其余的

我分享这个的原因是为了帮助你避免陷入特定的思维方式。 R.cond 是一个漂亮的 糟糕的 形式,如果我们完全诚实的话 – 它迫使您调整程序分支的语义,方法是将它封闭在一个数组中并创建 thunk 以保留您的程序可能永远不会使用的条件分支; true 惰性仅在 strictly-evaluated JavaScript using if/else?: 中可用;没有他们你还在做不必要的工作

一旦我们摆脱了像 R.cond 这样死板的形式,事情就会很自然地融合在一起 – 哎呀,我们甚至不需要 R.pipe,或者 R.pipeP,或者R 完全...

const fetchJSON = url =>
  fetch (url)
    .then (responseOK)
    .then (parseJSON)

const responseOK = (response) =>
  {
    if (response.status >= 200 && response.status < 300)
      return response
    else
      throw Object.assign (Error (response.statusText), { response })
  }

const parseJSON = response =>
  response.json ()
    
const fetchBin = (url) =>
  fetchJSON ('https://httpbin.org' + url)

fetchBin ('/anything?a=b') .then (console.log, console.error)
// all things good !
// => { args: {a: 'b'}, data: '' ... }

fetchBin ('/status/404') .then (console.log, console.error)
// non-200 status goes to error handler
// => { Error: NOT FOUND ..., response }

fetchBin ('/xml') .then (console.log, console.error)
// bad JSON goes to error handler
// => SyntaxError: Unexpected token < in JSON at position 0


好的,所以我们在那里不需要 R,但是这个答案并不意味着暗示一般 rule-of-thumb。 Ramda 是一个很棒的工具,可以教你很多关于函数式编程的知识——只记得有时退后一步,评估你的程序是否可以用 想要的方式表达,而不是担心关于语言(或库,或函数;R.cond)想要什么