Rescript编写socket.io绑定如何定义支持可选入参的高阶函数
解决方案
ReScript 完全支持定义这类可接受两种调用方式的函数签名,你只需要调整next类型的定义匹配 socket.io 原生的(err?: Error) => void接口即可。
核心修改点
将原来的next类型定义:
type next = (. unit) => unit
替换为可选参数版本:
type next = (. Js.Exn.t=?) => unit
这里的=?表示该参数为可选位置参数,调用时既可以不传参数直接写next(.)走正常放行逻辑,也可以传入错误对象next(., Js.Exn.makeError("ERROR!"))触发错误处理。
注意:你示例中用到的
Js.Exn.raiseError是直接抛出异常的 API,如果仅需要创建错误对象传给next,请使用Js.Exn.makeError。
修改后完整可运行代码
type server type socket type next = (. Js.Exn.t=?) => unit @new @module("socket.io") external socketIO: unit => server = "Server" @send external use: (server, (socket, next) => unit) => unit = "use" @send external listen: (server, int) => unit = "listen" @send external on: (server, @string [ #connection(socket => unit) ] ) => unit = "on" let io = socketIO() io->use((socket, next) => { Js.log("FIRST") next(.) }) io->use((socket, next) => { Js.log("SECOND") // 示例:校验失败时传入错误 let isAuthValid = false // 替换为实际校验逻辑 if !isAuthValid { next(., Js.Exn.makeError("身份校验失败")) } else { next(.) } }) io->on(#connection(socket => Js.log("CONNECT") )) io->listen(3000)
兼容旧版本 ReScript 的备用方案
如果你使用的是不支持 uncurried 函数可选参数的旧版本 ReScript,可以通过拆分两个绑定函数的方式实现相同效果:
type server type socket type next // 不预先定义函数签名 // 分别绑定两种调用方式 external nextOk: (. next) => unit = "" external nextFail: (. next, Js.Exn.t) => unit = "" @new @module("socket.io") external socketIO: unit => server = "Server" @send external use: (server, (socket, next) => unit) => unit = "use" @send external listen: (server, int) => unit = "listen" @send external on: (server, @string [ #connection(socket => unit) ] ) => unit = "on" // 调用示例 let io = socketIO() io->use((socket, next) => { // 正常放行 nextOk(. next) }) io->use((socket, next) => { // 触发错误 nextFail(. next, Js.Exn.makeError("ERROR!")) })
内容的提问来源于stack exchange,提问作者Octavia Kitsune
相关产品推荐
相关产品推荐

