# 脚本语言 (19_JavaScript)
最后更新: 2024-09-20
# 📚 概述
DarkM 框架的 JavaScript 模块提供了在 .NET 中执行 JavaScript 代码的能力。支持多种 JavaScript 引擎(ChakraCore、Node.js),实现动态脚本执行、规则引擎等功能。
源代码位置: DarkM/src/Framework/JavaScript
# 🏗️ 模块架构
# 项目结构
JavaScript/
├── JavaScript.Abstractions/ # 抽象层(接口、配置、枚举)
│ ├── IJavaScriptHandler.cs # JavaScript 处理接口
│ ├── JavaScriptConfig.cs # JavaScript 配置类
│ └── JavaScriptProvider.cs # JavaScript 提供器枚举
│
├── JavaScript.Integration/ # 集成层(DI 注册)
│ └── ServiceCollectionExtensions.cs # DI 扩展
│
├── JavaScript.ChakraCore/ # ChakraCore 实现
│ ├── ChakraCoreHandler.cs # ChakraCore 处理器
│ └── ChakraCoreHelper.cs # ChakraCore 帮助类
│
└── JavaScript.NodeJs/ # Node.js 实现
├── NodeJsHandler.cs # Node.js 处理器
└── NodeJsHelper.cs # Node.js 帮助类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 🔧 核心接口
# IJavaScriptHandler(JavaScript 处理)
/// <summary>
/// JavaScript 处理类
/// </summary>
public interface IJavaScriptHandler
{
/// <summary>
/// 异步执行 Js 方法
/// </summary>
/// <param name="module">Js 模块名</param>
/// <param name="functionName">Js 函数名</param>
/// <param name="args">Js 函数的参数</param>
/// <returns>执行结果</returns>
Task<T> ExecuteAsync<T>(
string module,
string functionName,
params object[] args);
/// <summary>
/// 执行 js 代码
/// </summary>
/// <typeparam name="T">返回类型</typeparam>
/// <param name="jsSourceCode">需要执行的 js 代码</param>
/// <returns>执行结果</returns>
Task<T> ExecuteAsync<T>(string jsSourceCode);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
功能说明:
ExecuteAsync<T>(module, functionName, args)- 执行指定模块的 JS 函数ExecuteAsync<T>(jsSourceCode)- 直接执行 JS 代码字符串
# JavaScriptProvider(JavaScript 提供器)
[Description("JavaScript 提供器")]
public enum JavaScriptProvider
{
/// <summary>
/// Microsoft ChakraCore 引擎
/// </summary>
ChakraCore,
/// <summary>
/// Node.js 引擎
/// </summary>
NodeJs
}
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
# JavaScriptConfig(JavaScript 配置)
public class JavaScriptConfig
{
/// <summary>
/// 提供器
/// </summary>
public JavaScriptProvider Provider { get; set; }
= JavaScriptProvider.ChakraCore;
}
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
# 🏗️ 依赖注入
# 自动注册机制
// JavaScript.Integration/ServiceCollectionExtensions.cs
public static class ServiceCollectionExtensions
{
/// <summary>
/// 添加 JavaScript 功能
/// </summary>
public static IServiceCollection AddJavaScript(
this IServiceCollection services,
IConfiguration cfg)
{
var config = new JavaScriptConfig();
var section = cfg.GetSection("JavaScript");
if (section != null)
{
section.Bind(config);
}
services.AddSingleton(config);
// 根据配置加载对应的实现程序集
var assembly = AssemblyHelper.LoadByNameEndString(
$".Lib.JavaScript.{config.Provider.ToString()}");
if (assembly == null)
return services;
// 注册 JavaScript 处理器
var handlerType = assembly.GetTypes()
.FirstOrDefault(m => m.Name.EndsWith("Handler"));
if (handlerType != null)
{
services.AddSingleton(typeof(IJavaScriptHandler), handlerType);
}
return services;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# 💡 使用示例
# 1. 配置 JavaScript 模块
// appsettings.json
{
"JavaScript": {
"Provider": "ChakraCore" // 或 NodeJs
}
}
1
2
3
4
5
6
2
3
4
5
6
# 2. 注册服务
// Program.cs 或 Startup.cs
var builder = WebApplication.CreateBuilder(args);
// 添加 JavaScript 服务
builder.Services.AddJavaScript(builder.Configuration);
var app = builder.Build();
1
2
3
4
5
6
7
2
3
4
5
6
7
# 3. 执行简单 JS 代码
public class JavaScriptExecutionService
{
private readonly IJavaScriptHandler _jsHandler;
private readonly ILogger<JavaScriptExecutionService> _logger;
public JavaScriptExecutionService(
IJavaScriptHandler jsHandler,
ILogger<JavaScriptExecutionService> logger)
{
_jsHandler = jsHandler;
_logger = logger;
}
/// <summary>
/// 执行简单计算
/// </summary>
public async Task<int> CalculateAsync()
{
var jsCode = @"
var a = 10;
var b = 20;
a + b;
";
var result = await _jsHandler.ExecuteAsync<int>(jsCode);
_logger.LogInformation("计算结果:{Result}", result);
return result; // 30
}
/// <summary>
/// 执行字符串处理
/// </summary>
public async Task<string> ProcessStringAsync()
{
var jsCode = @"
var str = 'Hello, World!';
str.toUpperCase();
";
var result = await _jsHandler.ExecuteAsync<string>(jsCode);
return result; // "HELLO, WORLD!"
}
/// <summary>
/// 执行 JSON 处理
/// </summary>
public async Task<JsonObject> ProcessJsonAsync()
{
var jsCode = @"
var data = { name: 'John', age: 30 };
data.city = 'New York';
data;
";
var result = await _jsHandler.ExecuteAsync<JsonObject>(jsCode);
return result; // { name: 'John', age: 30, city: 'New York' }
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
# 4. 执行 JS 模块函数
public class JsModuleService
{
private readonly IJavaScriptHandler _jsHandler;
public JsModuleService(IJavaScriptHandler jsHandler)
{
_jsHandler = jsHandler;
}
/// <summary>
/// 调用 JS 模块函数
/// </summary>
public async Task<T> CallJsFunctionAsync<T>(
string moduleName,
string functionName,
params object[] args)
{
return await _jsHandler.ExecuteAsync<T>(
moduleName,
functionName,
args);
}
}
// 使用示例
public class OrderCalculator
{
private readonly JsModuleService _jsService;
public OrderCalculator(JsModuleService jsService)
{
_jsService = jsService;
}
/// <summary>
/// 计算订单折扣
/// </summary>
public async Task<decimal> CalculateDiscountAsync(
decimal amount,
string customerLevel,
int points)
{
var discount = await _jsService.CallJsFunctionAsync<decimal>(
"discount-rules", // JS 模块名
"calculateDiscount", // 函数名
amount, // 参数 1
customerLevel, // 参数 2
points // 参数 3
);
return discount;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
# 5. 动态规则引擎
public class RuleEngineService
{
private readonly IJavaScriptHandler _jsHandler;
private readonly ILogger<RuleEngineService> _logger;
private readonly IMemoryCache _cache;
public RuleEngineService(
IJavaScriptHandler jsHandler,
ILogger<RuleEngineService> logger,
IMemoryCache cache)
{
_jsHandler = jsHandler;
_logger = logger;
_cache = cache;
}
/// <summary>
/// 执行动态规则
/// </summary>
public async Task<bool> ExecuteRuleAsync(
string ruleCode,
Dictionary<string, object> context)
{
// 从缓存获取编译后的规则
var cacheKey = $"rule_{ruleCode}";
var ruleScript = await _cache.GetOrCreateAsync(
cacheKey,
async entry =>
{
entry.AbsoluteExpirationRelativeToNow = TimeSpan.FromHours(1);
// 从数据库或配置加载规则脚本
var rule = await _ruleRepository.GetByCodeAsync(ruleCode);
return rule.Script;
});
// 构建执行上下文
var contextJson = JsonSerializer.Serialize(context);
var jsCode = $@"
var context = {contextJson};
{ruleScript}
";
try
{
var result = await _jsHandler.ExecuteAsync<bool>(jsCode);
_logger.LogInformation(
"规则 {RuleCode} 执行结果:{Result}",
ruleCode,
result);
return result;
}
catch (Exception ex)
{
_logger.LogError(
ex,
"规则 {RuleCode} 执行失败",
ruleCode);
throw;
}
}
/// <summary>
/// 执行价格计算规则
/// </summary>
public async Task<decimal> CalculatePriceAsync(
string ruleCode,
decimal basePrice,
Dictionary<string, object> factors)
{
factors["basePrice"] = basePrice;
var contextJson = JsonSerializer.Serialize(factors);
var ruleScript = await _ruleRepository.GetByCodeAsync(ruleCode);
var jsCode = $@"
var context = {contextJson};
{ruleScript}
";
var result = await _jsHandler.ExecuteAsync<decimal>(jsCode);
return result;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
# 6. JS 控制器示例
[Route("api/[controller]")]
[ApiController]
public class JavaScriptController : ModuleController
{
private readonly IJavaScriptHandler _jsHandler;
private readonly ILogger<JavaScriptController> _logger;
public JavaScriptController(
IJavaScriptHandler jsHandler,
ILogger<JavaScriptController> logger)
{
_jsHandler = jsHandler;
_logger = logger;
}
/// <summary>
/// 执行 JS 代码
/// </summary>
[HttpPost("execute")]
public async Task<IResultModel> ExecuteJs(
[FromBody] ExecuteJsRequest request)
{
try
{
var result = await _jsHandler.ExecuteAsync<object>(request.Code);
return ResultModel.Success(new
{
success = true,
result = result
});
}
catch (Exception ex)
{
_logger.LogError(ex, "JS 执行失败");
return ResultModel.Error($"JS 执行失败:{ex.Message}");
}
}
/// <summary>
/// 调用 JS 模块函数
/// </summary>
[HttpPost("call")]
public async Task<IResultModel> CallJsFunction(
[FromBody] CallJsFunctionRequest request)
{
try
{
var result = await _jsHandler.ExecuteAsync<object>(
request.Module,
request.Function,
request.Args);
return ResultModel.Success(new
{
success = true,
result = result
});
}
catch (Exception ex)
{
_logger.LogError(ex, "JS 函数调用失败");
return ResultModel.Error($"JS 函数调用失败:{ex.Message}");
}
}
/// <summary>
/// 验证 JS 代码
/// </summary>
[HttpPost("validate")]
public async Task<IResultModel> ValidateJs(
[FromBody] ValidateJsRequest request)
{
try
{
// 尝试执行简单的测试
var testCode = $@"
(function() {{
try {{
{request.Code}
return {{ valid: true }};
}} catch (e) {{
return {{ valid: false, error: e.message }};
}}
}})();
";
var result = await _jsHandler.ExecuteAsync<JsonElement>(testCode);
return ResultModel.Success(new
{
valid = result.GetProperty("valid").GetBoolean(),
error = result.TryGetProperty("error", out var error)
? error.GetString()
: null
});
}
catch (Exception ex)
{
return ResultModel.Error($"验证失败:{ex.Message}");
}
}
}
public class ExecuteJsRequest
{
public string Code { get; set; }
}
public class CallJsFunctionRequest
{
public string Module { get; set; }
public string Function { get; set; }
public object[] Args { get; set; }
}
public class ValidateJsRequest
{
public string Code { get; set; }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
# 🔧 引擎提供器对比
# JavaScript.ChakraCore(ChakraCore 引擎)
特点:
- ✅ Microsoft 官方维护(已停止更新)
- ✅ 轻量级,无需外部依赖
- ✅ 执行速度快
- ✅ 支持现代 JavaScript 语法(ES6+)
- ⚠️ 微软已停止维护(2020 年)
- ⚠️ 不支持 Node.js 模块
适用场景:
- 简单脚本执行
- 规则引擎
- 表达式计算
- 离线环境
安装:
# NuGet 包
Install-Package Microsoft.ChakraCore
1
2
2
# JavaScript.NodeJs(Node.js 引擎)
特点:
- ✅ 完整的 Node.js 运行时
- ✅ 支持所有 Node.js 模块(npm)
- ✅ 活跃的社区维护
- ✅ 支持异步编程
- ⚠️ 需要安装 Node.js
- ⚠️ 资源占用较大
适用场景:
- 复杂业务逻辑
- 需要 npm 模块
- 与现有 Node.js 代码集成
- 需要最新 ES 特性
安装:
# 安装 Node.js
# macOS
brew install node
# Windows
# 访问 https://nodejs.org/ 下载安装
# 验证安装
node --version
npm --version
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
# 💡 最佳实践
# 1. 脚本缓存
public class CachedJavaScriptService
{
private readonly IJavaScriptHandler _jsHandler;
private readonly IMemoryCache _cache;
public CachedJavaScriptService(
IJavaScriptHandler jsHandler,
IMemoryCache cache)
{
_jsHandler = jsHandler;
_cache = cache;
}
/// <summary>
/// 执行带缓存的脚本
/// </summary>
public async Task<T> ExecuteCachedAsync<T>(
string scriptKey,
Func<Task<string>> scriptLoader,
Dictionary<string, object> context)
{
var cacheKey = $"js_script_{scriptKey}";
var script = await _cache.GetOrCreateAsync(
cacheKey,
async entry =>
{
// 脚本缓存 1 小时
entry.AbsoluteExpirationRelativeToNow = TimeSpan.FromHours(1);
return await scriptLoader();
});
var contextJson = JsonSerializer.Serialize(context);
var jsCode = $@"
var context = {contextJson};
{script}
";
return await _jsHandler.ExecuteAsync<T>(jsCode);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# 2. 脚本超时控制
public class TimeoutJavaScriptService
{
private readonly IJavaScriptHandler _jsHandler;
private readonly ILogger<TimeoutJavaScriptService> _logger;
public TimeoutJavaScriptService(
IJavaScriptHandler jsHandler,
ILogger<TimeoutJavaScriptService> logger)
{
_jsHandler = jsHandler;
_logger = logger;
}
/// <summary>
/// 执行带超时的脚本
/// </summary>
public async Task<T> ExecuteWithTimeoutAsync<T>(
string jsCode,
TimeSpan timeout)
{
var cts = new CancellationTokenSource(timeout);
try
{
var task = _jsHandler.ExecuteAsync<T>(jsCode);
if (await Task.WhenAny(task, Task.Delay(timeout, cts.Token)) == task)
{
cts.Cancel();
return await task;
}
throw new TimeoutException(
$"JS 执行超时({timeout.TotalSeconds}秒)");
}
catch (OperationCanceledException)
{
throw new TimeoutException(
$"JS 执行超时({timeout.TotalSeconds}秒)");
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# 3. 脚本沙箱
public class SandboxJavaScriptService
{
private readonly IJavaScriptHandler _jsHandler;
private readonly ILogger<SandboxJavaScriptService> _logger;
public SandboxJavaScriptService(
IJavaScriptHandler jsHandler,
ILogger<SandboxJavaScriptService> logger)
{
_jsHandler = jsHandler;
_logger = logger;
}
/// <summary>
/// 在沙箱中执行脚本(限制危险操作)
/// </summary>
public async Task<T> ExecuteInSandboxAsync<T>(
string userCode,
Dictionary<string, object> allowedGlobals)
{
// 构建沙箱环境
var sandboxCode = @"
(function(sandbox) {
'use strict';
// 禁止访问危险对象
var require = undefined;
var process = undefined;
var global = undefined;
var eval = undefined;
var Function = undefined;
// 注入允许的全局对象
" + string.Join(";",
allowedGlobals.Select(kvp =>
$"var {kvp.Key} = sandbox.{kvp.Key};")) + @"
// 执行用户代码
try {
return (function() {
" + userCode + @"
})();
} catch (e) {
throw new Error('脚本执行错误:' + e.message);
}
})(this);
";
return await _jsHandler.ExecuteAsync<T>(sandboxCode);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
# 4. 脚本版本管理
public class VersionedScriptService
{
private readonly IJavaScriptHandler _jsHandler;
private readonly IScriptRepository _scriptRepo;
public VersionedScriptService(
IJavaScriptHandler jsHandler,
IScriptRepository scriptRepo)
{
_jsHandler = jsHandler;
_scriptRepo = scriptRepo;
}
/// <summary>
/// 执行指定版本的脚本
/// </summary>
public async Task<T> ExecuteVersionAsync<T>(
string scriptCode,
string version,
Dictionary<string, object> context)
{
// 获取指定版本的脚本
var script = await _scriptRepo.GetByVersionAsync(
scriptCode,
version);
if (script == null)
throw new ScriptNotFoundException(
$"脚本 {scriptCode} 版本 {version} 不存在");
var contextJson = JsonSerializer.Serialize(context);
var jsCode = $@"
var context = {contextJson};
var version = '{version}';
{script.Content}
";
return await _jsHandler.ExecuteAsync<T>(jsCode);
}
/// <summary>
/// 执行最新版本脚本
/// </summary>
public async Task<T> ExecuteLatestAsync<T>(
string scriptCode,
Dictionary<string, object> context)
{
var script = await _scriptRepo.GetLatestAsync(scriptCode);
var contextJson = JsonSerializer.Serialize(context);
var jsCode = $@"
var context = {contextJson};
var version = '{script.Version}';
{script.Content}
";
return await _jsHandler.ExecuteAsync<T>(jsCode);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
# 🔍 常见问题
# Q1: ChakraCore 不支持某些 ES6 特性?
解决方案:
- ✅ 使用 Babel 转译代码为 ES5
- ✅ 切换到 Node.js 引擎
- ✅ 避免使用最新 ES 特性
// 使用 Babel 转译
public class BabelJavaScriptService
{
public async Task<string> TranspileAsync(string es6Code)
{
// 调用 Babel API 转译
var transpiled = await _babelApi.TranspileAsync(es6Code);
return transpiled;
}
}
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
# Q2: 如何调试 JS 代码?
解决方案:
public class DebugJavaScriptService
{
private readonly IJavaScriptHandler _jsHandler;
private readonly ILogger<DebugJavaScriptService> _logger;
public async Task<T> ExecuteWithDebugAsync<T>(
string jsCode,
Dictionary<string, object> context)
{
// 记录输入的 JS 代码
_logger.LogInformation("执行 JS 代码:\n{Code}", jsCode);
// 记录上下文
_logger.LogInformation("上下文:{Context}",
JsonSerializer.Serialize(context));
try
{
var result = await _jsHandler.ExecuteAsync<T>(jsCode);
_logger.LogInformation("执行结果:{Result}",
JsonSerializer.Serialize(result));
return result;
}
catch (Exception ex)
{
_logger.LogError(ex, "JS 执行失败");
throw;
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# Q3: 如何处理异步 JS 代码?
解决方案:
// 确保 JS 代码返回 Promise
public async Task<T> ExecuteAsyncCodeAsync<T>(string jsCode)
{
var wrappedCode = $@"
(async function() {{
try {{
{jsCode}
}} catch (e) {{
throw new Error('异步代码执行失败:' + e.message);
}}
}})();
";
return await _jsHandler.ExecuteAsync<T>(wrappedCode);
}
// 使用示例
var jsCode = @"
await new Promise(resolve => setTimeout(resolve, 1000));
return '完成';
";
var result = await ExecuteAsyncCodeAsync<string>(jsCode);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 📚 相关文档
# 🔗 参考链接
- 源代码 (opens new window) -
src/Framework/JavaScript - ChakraCore GitHub (opens new window)
- Node.js 官网 (opens new window)
最后更新: 2024-09-20