javascript - 来自 javascript 绑定(bind)的未标记联合走上了错误的道路

标签 javascript ocaml reason bucklescript union-types

我正在尝试为 amqplib npm 包编写一个 Reasonml 绑定(bind):

http://www.squaremobius.net/amqp.node/

特别是这个函数:

http://www.squaremobius.net/amqp.node/channel_api.html#channel_get

class type amqpMessageT = [@bs] {
  pub content: nodeBuffer
};

type amqpMessage = Js.t(amqpMessageT);

type gottenMessage = Js.Nullable.t(amqpMessage);

type qualifiedMessage = Message(gottenMessage) | Boolean(bool);

class type amqpChannelT = [@bs] {
  pub assertQueue: string => queueParams => Js.Promise.t(unit);
  pub consume: string => (amqpMessage => unit) => unit;
  pub ack: amqpMessage => unit;
  pub get: string => Js.Promise.t(qualifiedMessage);
  pub purgeQueue: string => Js.Promise.t(unit);
  pub deleteQueue: string => Js.Promise.t(unit);
  pub sendToQueue: string => nodeBuffer => messageParams => unit;
};

然后我有以下代码:

 ....
 channel##get("MyQueue")
 |> Js.Promise.then_(message => {
   switch message {
     | Boolean(false) => Js.Promise.resolve(Js.log("No Message"));
     | Message(msg) => Js.Promise.resolve(Js.log("Has Message, Will Travel"));
     | Boolean(true) => Js.Promise.resolve(Js.log("Impossible Message"!));
   }
  }

但是,即使 js 调用返回 false,这总是会沿着“Message(msg)”路径走下去。

现在添加以下绑定(bind):

let unsafeGet: amqpChannel => string => Js.Promise.t(gottenMessage) = [%bs.raw{|function(channel, queueName) {
  return channel.get(queueName).then((value) => {
    if(value === false) {
      return Promise.resolve(null)
    } else {
      return Promise.resolve(value)
    }
  })
}|}];

我已经能够回避这个问题,但老实说,我不太喜欢使用 bs.raw 。我的初始未标记联合类型有什么问题?我该如何解决这个问题?

最佳答案

OCaml 语言中没有未标记的联合类型,也没有运行时类型信息,因此您必须实现自己的类型、检查和转换以将其转换为可用的形式。

例如,您可以使用抽象类型来表示“未知”类型,并使用伴随函数来检查其类型,将其转换为该类型,然后将其转换为 qualifiedMessage:

type unknownMessage;

let classifyMessage = (value: unknownMessage) =>
  switch (Js.Types.classify(value)) {
  | JSString(s) => Message(Js.Nullable.return(s))
  | JSNull      => Message(Js.null)
  | JSFalse     => Boolean(false)
  | JSTrue      => Boolean(true)
  | _           => failwith("invalid runtime type")
  }

此外,作为旁注,如果您通过公开抽象类型和函数/外部而不是公开“原始”对象来抽象底层数据结构,您将在定义接口(interface)和隐藏的方式方面获得很大的灵活性这个额外的转换步骤。

关于javascript - 来自 javascript 绑定(bind)的未标记联合走上了错误的道路,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51398556/

相关文章:

javascript - 具有多个域的单个 Meteor 应用程序

javascript - 如何从不同对象范围访问 knockout 可观察量

garbage-collection - 关于OCaml GC的minor/young heap

ocaml - 何时使用管道 |> 与参数

graphql - Reason React 和 Graphql 处理 ENUM 值

javascript - 无法从由 Jquery 加载到另一个 html 的 HTML 中定位类

function - 是否可以在不丢失 ocaml 中参数的多态类型的情况下设置函数的默认值

thread-safety - 在 OCaml 中的 POSIX 线程之间共享引用时的线程安全

string - 将字符串拆分为字符列表的最简单方法是什么?

javascript - 为 html 元素赋值并读取它