在ClearScript V8中无法异步执行HTTP请求的问题求助
解决ClearScript V8异步HTTP请求返回null的问题
问题原因
ClearScript的engine.Execute是同步执行逻辑,当你在脚本中用await调用.NET异步方法时,脚本内的异步操作并未被等待——engine.Execute会直接执行后续C#代码,此时异步请求还没完成,hostVariables.asyncResponse自然还是null。
解决方案
你需要把脚本逻辑封装成异步函数,然后在C#中等待这个异步函数执行完毕。ClearScript完全支持异步操作,你的需求是可行的,并非受限于框架特性,只是之前的等待逻辑有误。
修改后的代码示例
public class Javascript : Controller { public async Task<IActionResult> Index() { var hostVariables = new HostVariables(); using (var engine = new V8ScriptEngine()) { engine.DocumentSettings.AccessFlags = DocumentAccessFlags.None; engine.AddHostType(typeof(Console)); using (HttpClient client = new HttpClient()) { var request = new Request(client); engine.AddHostObject("hostVariables", hostVariables); engine.AddHostObject("request", request); // 封装为自执行异步函数,用EvaluateAsync等待完成 await engine.EvaluateAsync(new DocumentInfo { Category = ModuleCategory.Standard }, @" (async function() { hostVariables.syncResponse = request.get(""https://www.google.com"").responseText; hostVariables.asyncResponse = (await request.getAsync(""https://www.google.com"")).responseText; })(); "); } } // 此时asyncResponse已正确获取到响应内容 return View(); } } // 以下辅助类保持原代码不变 public class HostVariables { public string syncResponse { get; set; } public string asyncResponse { get; set; } } public class Request { private HttpClient _client; public Request(HttpClient client) { _client = client; } public Response get(string url) { var response = new Response(); var getResponse = _client.GetAsync(url).Result; var encoding = ASCIIEncoding.ASCII; response.statusCode = (int)getResponse.StatusCode; if (getResponse.Content != null) response.responseText = getResponse.Content.ReadAsStringAsync().Result; if (getResponse.Headers != null) response.responseHeaders = getResponse.Headers.Select(x => new ResponseHeader() { key = x.Key, value = x.Value.ToArray() }).ToArray(); return response; } public async Task<Response> getAsync(string url) { var response = new Response(); var getResponse = await _client.GetAsync(url); var encoding = ASCIIEncoding.ASCII; response.statusCode = (int)getResponse.StatusCode; if (getResponse.Content != null) response.responseText = await getResponse.Content.ReadAsStringAsync(); if (getResponse.Headers != null) response.responseHeaders = getResponse.Headers.Select(x => new ResponseHeader() { key = x.Key, value = x.Value.ToArray() }).ToArray(); return response; } } public class Response { public string? responseText; public ResponseHeader[]? responseHeaders; public int? statusCode; } public class ResponseHeader { public string? key; public string[]? value; }
关键改动说明
- 用
engine.EvaluateAsync替代engine.Execute,并通过await等待异步脚本执行完成 - 将脚本逻辑包裹在自执行的异步函数中,确保
await request.getAsync(...)能正确等待异步请求完成
额外优化建议
- 实际项目中建议复用
HttpClient单例,避免频繁创建实例导致的socket资源耗尽问题 - 可以考虑给
Request类添加异步方法的错误处理逻辑,避免未捕获异常导致脚本执行失败
内容的提问来源于stack exchange,提问作者Matt Spinks
相关产品推荐
相关产品推荐

