Kotlin中Lambda作为最后参数时()与{}调用差异致Vert.x接口挂起
Vert.x REST API 挂起问题排查:Kotlin Lambda调用误区
我用Vert.x实现了RestfulServer类,运行后浏览器调用REST API出现挂起问题,但注释掉corsHandling()方法后就恢复正常。排查后发现问题不在CorsHandler本身,而是Kotlin中调用handler方法的方式出错了。
代码对比
正常运行的代码
用()传入CorsHandler实例的写法能正常工作:
private fun corsHandling(): Route = router.route().handler( // 此处使用() CorsHandler .create("*") .allowedMethods(mutableSetOf(HttpMethod.GET, HttpMethod.HEAD, HttpMethod.OPTIONS)) )
导致挂起的代码
用{}包裹的写法会让接口挂起:
private fun corsHandling(): Route = router.route().handler{ // 此处使用{} CorsHandler .create("*") .allowedMethods(mutableSetOf(HttpMethod.GET, HttpMethod.HEAD, HttpMethod.OPTIONS)) }
两者的唯一区别就是调用handler时用了()还是{}。Kotlin里Lambda作为最后参数时可以省略括号,但这里的情况是个例外——本质是误把handler调用写成了嵌套Lambda的形式。
问题本质解析
用下面的简化示例就能看清问题核心:
fun takesSingleLambda(func: ()-> Unit) { func() } fun main() { println("1") takesSingleLambda( returnsLambda() ) println("2") takesSingleLambda{ returnsLambda() } println("3, which does exactly the same as 2") takesSingleLambda({ returnsLambda() }) } fun returnsLambda() = { // 类似CorsHandler.create("*").allowedMethods(...) println("executing") }
- 第一种调用(
takesSingleLambda(returnsLambda())):直接传入returnsLambda()的返回值(一个() -> Unit类型的Lambda),takesSingleLambda会执行这个Lambda,所以会输出"executing"。 - 第二、三种调用:用
{}包裹returnsLambda(),相当于传入了一个() -> () -> Unit类型的Lambda——takesSingleLambda执行这个外层Lambda时,只是得到了内层Lambda,但并没有执行它,所以不会输出"executing"。
对应到Vert.x的场景:
- 正确写法是直接把实现了
Handler<RoutingContext>的CorsHandler实例传给handler方法,它会处理请求并返回响应。 - 错误写法传入的是一个返回CorsHandler的Lambda,这个Lambda被执行后只是返回了CorsHandler,但并没有让CorsHandler去处理请求,导致请求一直得不到响应,最终挂起。
内容的提问来源于stack exchange,提问作者Vencat
相关产品推荐
相关产品推荐

