【问题标题】:Converting from Js.Promise to `reason-promise` in ReasonML在 ReasonML 中从 Js.Promise 转换为 `reason-promise`
【发布时间】:2021-01-06 21:26:52
【问题描述】:

我有一个库使用reason-promise 作为默认分支而不是另一个分支的情况。我发现很难从一个分支切换到另一个分支,因为我一生都无法弄清楚如何使用reason-promise。我在 Js.Promise 方面并没有好多少,但这不是重点。

有问题的图书馆是reason-apollo-client。该分支还有许多其他改进,包括 reason-promise 作为默认的 promise 实现。该分支是next branch

例如,在reason-promise-question 找到,我有一个Js.Promise 函数,它可以让我获得当前的令牌值。它有以下类型:

unit => Js.Promise.t(
  Js.Nullable.t(string)
)

该功能可在Tokens 中找到,转载如下。这是一个哑函数,没有绑定。关键是看如何让它编译。

[@bs.val] [@bs.scope "localStorage"]
external setItem: (string, string) => unit = "setItem";
let setUserToken: string => Js.Promise.t(unit) =
  token => Js.Promise.resolve(setItem("auth", token));

[@bs.val] [@bs.scope "localStorage"]
external getItem: string => Js.Nullable.t(string) = "getItem";
let getUserToken: unit => Js.Promise.t(Js.Nullable.t(string)) =
  () => Js.Promise.resolve(getItem("auth"));

let setTempUserToken: string => Js.Promise.t(unit) =
  _ => Js.Promise.resolve();

let getTempUserToken: unit => Js.Promise.t(Js.Nullable.t(string)) =
  () => Js.Promise.resolve(Js.Nullable.undefined);

当我在创建apollo/client authlink 时尝试将其与reason-promise 一起使用时,出现以下错误:

unit => Js.Promise.t(
  Js.Nullable.t(string)
)
Error: This expression has type
         Js.Promise.t(Js.Json.t) = Js.Promise.t(Js.Json.t)
       but an expression was expected of type
         Promise.t(Js.Json.t) = Promise.rejectable(Js.Json.t, Promise.never)

这里是authlink 函数:

let authLink =
  ApolloClient.Link.ContextLink.makeAsync((~operation as _, ~prevContext as ctx) => {
    Tokens.getUserToken()
    ->Js.Promise.then_(
        token => {
          switch (token->Js.Nullable.toOption) {
          | None =>
            Tokens.getTempUserToken()
            ->Js.Promise.then_(
                token => Js.Promise.resolve(Js.Nullable.toOption(token)),
                _,
              )
          | Some(token) => Js.Promise.resolve(Some(token))
          }
        },
        _,
      )
    ->Js.Promise.then_(
        fun
        | None => Js.Promise.resolve(Js.Json.null)
        | Some(token) => {
            Js.Promise.resolve(
              [%raw
                {| (context, token) => ({
                headers: {
                  ...ctx.headers,
                  authorization: `Bearer ${token}`
                }
              }) |}
              ](
                ctx,
                token,
              ),
            );
          },
        _,
      )
  });

我们如何将其转换为理性承诺?请随意随心所欲。

提前谢谢你。

【问题讨论】:

    标签: promise apollo-client reason bucklescript


    【解决方案1】:

    您应该能够将您的原版Js.Promise.t 转换为Promise.t

    首先,您必须将Js.Promise.t 转换为Promise.Js.t。这可以通过

    let myIntermediatePromise = myJsPromise |>  Promise.Js.fromBsPromise
    

    之所以存在额外的Promise.Js.t 类型,是因为Js.Promise.tPromise.t 的错误处理理念不同。后者使用Belt.Result 模块处理错误(如https://github.com/aantron/promise#handling-errors-with-result 所示),而前者使用拒绝(通常使用catch(在JavaScript 中)或catch_(在Reason 中)处理)。 Promise.Js.t 的中间产品封装了与 JavaScript 承诺相同的理念。

    为了将中间产品转换为最终的Promise.t,因此您需要明确指出当/如果中间承诺被拒绝时应该发生什么。这可以通过几种不同的方式完成,但作为示例,您可以这样做:

    let myFinalPromise = myIntermediatePromise |> Promise.Js.toResult
    

    这会将您原来的Js.Promise.t('a) 转换为Promise.t(Result('a, Js.Promise.error))

    如果您想进一步转换为Promise.t('a),您必须明确处理可能出现的错误。

    更多详情请见https://github.com/aantron/promise#advanced-rejection

    注意,看起来 apollo 已经开始使用原版 promise (https://github.com/reasonml-community/reason-apollo-client/pull/57)。

    【讨论】:

      猜你喜欢
      • 2021-01-10
      • 1970-01-01
      • 1970-01-01
      • 2022-10-13
      • 2020-09-28
      • 2019-12-14
      • 2016-08-11
      • 2017-01-12
      • 2016-07-05
      相关资源
      最近更新 更多