如何处理 scala.js 外观中的可为空值?
How to deal with nullable values in scala.js facades?
我正在尝试为 request 库编写一个 Scalajs facade,它有一个使用回调模式的方法:
request('http://www.google.com', function (error, response, body) {
console.log('error:', error); // Print the error if one occurred
console.log('statusCode:', response && response.statusCode); // Print the response status code if a response was received
console.log('body:', body); // Print the HTML for the Google homepage.
});
在此模式中,error
为 null 且 response
和 body
已定义,反之亦然。
在 ScalaJS 外观中反映此模式的最佳方式是什么?我能想到的最好的是:
@js.native
@JSImport("request", JSImport.Default)
object Request extends js.Object {
def apply[A](uri: String,
requestConfig: js.Object,
callback: js.Function2[js.JavaScriptException, Response, A]): Unit = js.native
}
执行该方法后,我使用 Option
来匹配正确的大小写:
Request(url, RequestConfig(queryString, headers), (error, response) => {
(Option(error), Option(response)) match {
case (Some(err), _) => // handle error
case (_, Some(res)) => // handle success
case (None, None) => // This will only happen if there is a bug in the request library
}
})
我不喜欢这样,因为 1) 我必须为 (None, None)
编写不必要的匹配项或忽略非详尽匹配警告,以及 2) 外观没有准确描述类型。
我也尝试过使用 js.UndefOr[js.JavaScriptException]
但是这个 returns 来自 .toOption
和 js.JavaScriptException | Null
的 Some(null)
但我似乎只能将其转换为Option[js.JavaScriptException | Null]
.
与undefined
不同,Scala.js没有给你专门的工具来处理null
。
这是因为在 Scala 中一切都可以为空(我们中的许多人都不喜欢这个事实,包括我自己,但那是另一回事)。
因此,我们必须争辩说,外观 确实 准确地描述了 Scala / Scala.js 类型系统可能的类型。
如果您需要经常使用它,@Thilo 建议的包装器确实是您的最佳选择:
object RichRequest {
def apply(uri: String, req: RequestConfig): Future[Response] = {
val p = Promise[Response]()
Request(uri, req, (error, response) => {
if (error != null) p.failure(error)
else p.success(response)
})
p.future
}
}
或者,如果您想保持基于 API 回调,请考虑使用 Try
。
请注意,如果您想走这条路,请考虑使用 request-promise-native 开箱即用(使用 JavaScript 承诺)。
所以你的门面会变成:
@js.native
@JSImport("request-promise-native", JSImport.Default)
object Request extends js.Object {
def apply(uri: String, requestConfig: js.Object): js.Promise[Response] = js.native
}
以及调用站点:
Request(url, RequestConfig(...)).toFuture
我正在尝试为 request 库编写一个 Scalajs facade,它有一个使用回调模式的方法:
request('http://www.google.com', function (error, response, body) {
console.log('error:', error); // Print the error if one occurred
console.log('statusCode:', response && response.statusCode); // Print the response status code if a response was received
console.log('body:', body); // Print the HTML for the Google homepage.
});
在此模式中,error
为 null 且 response
和 body
已定义,反之亦然。
在 ScalaJS 外观中反映此模式的最佳方式是什么?我能想到的最好的是:
@js.native
@JSImport("request", JSImport.Default)
object Request extends js.Object {
def apply[A](uri: String,
requestConfig: js.Object,
callback: js.Function2[js.JavaScriptException, Response, A]): Unit = js.native
}
执行该方法后,我使用 Option
来匹配正确的大小写:
Request(url, RequestConfig(queryString, headers), (error, response) => {
(Option(error), Option(response)) match {
case (Some(err), _) => // handle error
case (_, Some(res)) => // handle success
case (None, None) => // This will only happen if there is a bug in the request library
}
})
我不喜欢这样,因为 1) 我必须为 (None, None)
编写不必要的匹配项或忽略非详尽匹配警告,以及 2) 外观没有准确描述类型。
我也尝试过使用 js.UndefOr[js.JavaScriptException]
但是这个 returns 来自 .toOption
和 js.JavaScriptException | Null
的 Some(null)
但我似乎只能将其转换为Option[js.JavaScriptException | Null]
.
与undefined
不同,Scala.js没有给你专门的工具来处理null
。
这是因为在 Scala 中一切都可以为空(我们中的许多人都不喜欢这个事实,包括我自己,但那是另一回事)。
因此,我们必须争辩说,外观 确实 准确地描述了 Scala / Scala.js 类型系统可能的类型。
如果您需要经常使用它,@Thilo 建议的包装器确实是您的最佳选择:
object RichRequest {
def apply(uri: String, req: RequestConfig): Future[Response] = {
val p = Promise[Response]()
Request(uri, req, (error, response) => {
if (error != null) p.failure(error)
else p.success(response)
})
p.future
}
}
或者,如果您想保持基于 API 回调,请考虑使用 Try
。
请注意,如果您想走这条路,请考虑使用 request-promise-native 开箱即用(使用 JavaScript 承诺)。
所以你的门面会变成:
@js.native
@JSImport("request-promise-native", JSImport.Default)
object Request extends js.Object {
def apply(uri: String, requestConfig: js.Object): js.Promise[Response] = js.native
}
以及调用站点:
Request(url, RequestConfig(...)).toFuture