# aardio 范例: web.view( WebView2 浏览器控件) - 调用 JS 函数



```aardio
//web.view( WebView2 浏览器控件) - 调用 JS 函数
import win.ui;
/*DSG{{*/
var winform = win.form(text="WebView2 - 调用 JS 函数";right=966;bottom=622)
winform.add(
btnCallJavaScript={cls="button";text="调用 JS 函数";left=615;top=537;right=869;bottom=606;color=0xD77800;anchors={right=1;bottom=1};font=LOGFONT(h=-14);note="在 aardio 中调用 JavaScript 函数。";z=2};
static={cls="static";left=8;top=6;right=956;bottom=503;anchors={left=1;top=1;right=1;bottom=1};z=1}
)
/*}}*/

import web.view;
var wb = web.view(winform.static);

/*
第一原则：在 JS 与 aardio 代码交互时应避免同步发起反向调用。
违反此原则可能导致 WebView2 调用异常、卡顿等问题。

- 在 aardio 中调用 JS 总是异步发起调用，
但 调用 wb.eval, wb.xcall 时默认会阻塞等待 JS 返回值，
除非在指定了接收 JS 返回值的回调函数（异步调用，不会阻塞调用代码）。

在被网页回调的 aardio 函数内部应避免阻塞调用导致阻塞后续调用。
如果不需要返回值，改用 wb.invoke, wb.doScript 更轻量且不需要处理返回值与回调。
或者通过 winform.setTimeout, thread.invoke 也可以异步执行代码。

- 在 JS 中虽然 aardio 函数的返回值是异步对象，但这不等于发起调用的过程是异步的。
一个正被 aardio 回调的 JS 函数内如果要反向回调 aardio，则应通过 setTimeout 异步发起调用。
*/

// aardio 按钮事件
winform.btnCallJavaScript.oncommand = function(id,event){
	
	/*
	wb.xcall 阻塞调用 JS 全局函数并等待 JS 返回值，
	参数 @1 指定函数名，可添加任个调用参数。
	*/
	wb.xcall("setData",{
		name = "测试1";
		passowrd = "123456"
	}); 
	
	/*

	
	调用 wb.eval, wb.xcall 时默认会阻塞等待 JS 返回值，
	除非在指定了接收 JS 返回值的回调函数（异步调用，不会阻塞调用代码）。
	在被网页回调的 aardio 函数内部应避免阻塞调用导致阻塞后续调用。
	如果不需要返回值，改用 wb.invoke, wb.doScript 更轻量且不需要处理返回值与回调

	wb.invoke 的用法与 wb.xcall 相同，
	唯一的区别是 wb.invoke 不会阻塞并等待返回值。
	
	**使用 WebView2 应当异步优先**：
	总是优先用 wb.invoke, wb.doScrip 这样异步非阻塞的函数。
		
	回调 JS 函数: https://www.aardio.com/zh-cn/docs/examples/WebUI/web.view/js-callback.html
	*/
	
	/*
	如果参数@1 不包含回车、换行、分号、大括号，圆括号，
	则最后一个点号前的对象设为被调用函数的 this 参数。
	*/
	wb.invoke("emitter.emit",
		"setData",{
		name = "测试2";
		passowrd = "123456"
	}); 
	
	//参数 @1 也可以指定返回函数对象的 JS 表达式。 
	wb.invoke("function(args){
		emitter.emit('setData',args)
	}", {
		name = "测试3";
		passowrd = "123456"
	});  
}

wb.external = {
	nativeFunc = function(str){
		winform.text = str;
	} 
}

wb.html = /**
<!DOCTYPE html><html>
<head>
	<meta charset="utf-8" /> 
	<script>!function(e,n){"object"==typeof exports&&"undefined"!=typeof module?module.exports=n():"function"==typeof define&&define.amd?define(n):(e=e||self).mitt=n()}(this,function(){return function(e){return{all:e=e||new Map,on:function(n,t){var f=e.get(n);f?f.push(t):e.set(n,[t])},off:function(n,t){var f=e.get(n);f&&(t?f.splice(f.indexOf(t)>>>0,1):e.set(n,[]))},emit:function(n,t){var f=e.get(n);f&&f.slice().map(function(e){e(t)}),(f=e.get("*"))&&f.slice().map(function(e){e(n,t)})}}}});
	emitter = mitt();//github.com/developit/mitt </script> 
</head>
<body>  

<script> 

	//响应事件
	emitter.on("setData", function(v){
		document.body.insertAdjacentHTML("beforeEnd", JSON.stringify(v) + "<br>" )
	} );
	
	//定义全局函数
	window.setData = function(v){
		document.body.insertAdjacentHTML("beforeEnd", JSON.stringify(v) + "<br>" )
		
		//正被 aardio 回调的 JS 反向回调 aardio 时仍应使用 setTimeout 异步发起调用
		setTimeout(()=>{
			aardio.nativeFunc("正被 aardio 回调的 JS 函数反向回调 aardio 函数")
		})
	} 
		
</script>
	
</body> 
**/

winform.show();
win.loopMessage();
```

