fable-compiler / Fable

F# to JavaScript, TypeScript, Python, Rust and Dart Compiler
http://fable.io/
MIT License
2.92k stars 298 forks source link

Q: What is the proper way to create native objects like WebSockets? #3341

Closed MaxWilsonMS closed 1 year ago

MaxWilsonMS commented 1 year ago

Besides using Emit, what is the right way to create a WebSocket? Import doesn't seem to work because it's a native module, not a JS module:

[<Import("default", from="WebSocket")>]
let t : WebSocketType = jsNative
let createSocket clientUrl protocol : WebSocket =
    t.Create (clientUrl, U2.Case1 protocol)

[vite] Internal server error: Failed to resolve import "WebSocket" from "src\WebSync.fs.js". Does the file exist?

Obviously I can just do

[<Emit("new WebSocket($0, $1)")>]
let createSocket clientUrl protocol : WebSocket = jsNative

but then that makes me wonder why WebSocketType exists and whether there's a different way.

SCullman commented 1 year ago

It is part of fable-browser; there is a NuGet package for it.

MaxWilsonMS commented 1 year ago

@SCullman, I am consuming the Nuget package via \<PackageReference Include="Fable.Browser.WebSocket" Version="1.3.0" />. That's why I have WebSocketType in the first place. But how do you instantiate a WebSocket without using Emit, and what is WebSocketType for? That is my question.

MangelMaxime commented 1 year ago

@MaxWilsonMS You can create a web socket by doing WebSocket.Create

WebSocketType is how the constructor or equivalent for it is exposed. This is because we can't or could not use the native F# constructor to map to JS binding constructor.

MaxWilsonMS commented 1 year ago

I've tried:

Browser.Types.WebSocket.Create // compile error: there is no static Create method

(null :?> Browser.Types.WebSocket).Create // also compile error: there is no instance Create method

let webSocket: WebSocket = Fable.Core.JsInterop.import "WebSocket" ""
let actualWebSocket = webSocket.Create // also compile error: there is no instance create

let webSocketType: WebSocketType = Fable.Core.JsInterop.import "WebSocket" ""
let actualWebSocket = webSocketType.Create // compiles but fails at runtime of course because "" is not a js module

Could you post a code snippet?

MangelMaxime commented 1 year ago

You don't want to access the Types but the WebSocket global as in JavaScript:

open Browser

let socket = WebSocket.Create("wss://demo.piesocket.com/v3/channel_123?api_key=VCXCEuvhGcBDP7XhiJJUDvR1e1D3eiVjgZ9VRiaV&notify_self")

socket.onopen <- fun ev ->
    console.log("Socket connected: ", ev)

socket.onmessage <- fun ev ->
    console.log("New message received:")
    console.log ev.data
MaxWilsonMS commented 1 year ago

Oh, I see.

Browser.WebSocket.WebSocket.Create(clientUrl, U2.Case1 "json.webpubsub.azure.v1")

Thanks!