Skip to content

JavaScript互操作

CefBrowser控件在twinBASIC和页面中运行的JavaScript之间提供两座互补的桥:

  1. 消息 —— 在两个方向推送值(字符串、数字……)并在另一侧监听。
  2. 脚本调用 —— 从BASIC调用命名的JavaScript函数,并(可选)等待其返回值。

INFO

WebView2还暴露了第三座桥——宿主对象,其中BASIC类发布到 chrome.webview.hostObjects.<Name> 供页面调用。CEF包尚未暴露等效功能——参见参考的WebView2对等部分。

本教程涵盖两座桥,每个BASIC端旁边显示匹配的JavaScript端。工作代码来自示例1b——Chromium Embedded Framework示例(窗体示例2)。

桥1——消息

消息是在两个方向传递的值。当你不希望提前定义方法签名时,用于通知和临时数据负载。

BASIC → 页面

PostWebMessage向页面发送值;页面通过 window.chrome.webview 上的 message 事件接收它:

vb
WebView.PostWebMessage "Hello from twinBASIC!"
js
window.chrome.webview.addEventListener('message', (e) => {
    alert("Host sent: " + e.data);
});

字符串以JavaScript字符串到达;数值、BooleanNullEmpty为页面进行JSON编码。对象和数组目前不支持。

如果在渲染器IPC连接之前调用PostWebMessage,调用会排队并在连接建立后分发——无需显式等待Ready

页面 → BASIC

页面调用 window.chrome.webview.postMessage(value);BASIC通过JsMessage事件接收它:

js
function sendHostAMessage() {
    window.chrome.webview.postMessage("This is a message from JavaScript.");
}
vb
Private Sub WebView_JsMessage(ByVal Message As Variant) _
        Handles WebView.JsMessage
    Debug.Print "Page sent: "; Message
End Sub

两个半部形成请求/响应交换——页面发送查询字符串,BASIC处理它并返回结果:

vb
Private Sub WebView_JsMessage(ByVal Message As Variant) _
        Handles WebView.JsMessage
    If Left$(Message, 6) = "QUERY:" Then
        WebView.PostWebMessage "ANSWER:" & LookupAnswer(Mid$(Message, 7))
    End If
End Sub

桥2——脚本调用

当页面暴露命名的JS函数时,BASIC可以直接调用它们。有三种变体:

方法返回值使用场景
JsRunVariant,同步你需要内联结果且JS是纯的(无回调)。
JsRunAsync无;结果通过 JsAsyncResultJS可能需要一段时间,你不想阻塞UI。
ExecuteScript无(即发即弃)你只想触发某些操作——不需要返回值。

JsRun(同步)

给定一个页面端函数:

js
function multiplyTheseNumbers(a, b) {
    return a * b;
}

BASIC可以调用它并在同一行读取结果:

vb
Dim product As Long = WebView.JsRun("multiplyTheseNumbers", 5, 6)
Debug.Print product   ' 30

调用会阻塞BASIC线程,直到渲染器进程回复。

WARNING

如果JavaScript函数在调用期间回调到BASIC——例如通过 window.chrome.webview.postMessage(...)——结果是死锁。仅对纯函数使用JsRun;不符合此条件时改用JsRunAsync。完整讨论参见重入性教程

JsRunAsync(异步)

vb
Private Sub btnRun_Click() Handles btnRun.Click
    WebView.JsRunAsync "multiplyTheseNumbers", 5, 6
End Sub

Private Sub WebView_JsAsyncResult( _
        ByVal Result As Variant, Token As LongLong, ErrString As String) _
        Handles WebView.JsAsyncResult
    If LenB(ErrString) = 0 Then
        Debug.Print "Async result: "; Result
    Else
        Debug.Print "Async error: "; ErrString
    End If
End Sub

JsAsyncResult事件包含Token参数,因此单个处理程序可以解复用多个进行中的调用。成功时ErrString为空。

在渲染器IPC连接之前进行的调用会排队并在连接建立后分发。

ExecuteScript(即发即弃)

vb
WebView.ExecuteScript "startTimer()"

无返回值,无事件。推动页面执行某些操作的最简单方式。

重入性

关于从BASIC调用同步JavaScript何时安全——以及不安全时该怎么做——的讨论在其自己的教程中。简短概述:

  • 纯JS(输入→输出,无涉及宿主的副作用):JsRun可行。
  • 可能回发消息、等待宿主对象或以其他方式重入BASIC的JS:使用JsRunAsync

完整图景参见重入性教程

下一步

twinBASIC及其LOGO版权为作者"韦恩"所有