You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在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;
}

关键改动说明

  1. 用engine.EvaluateAsync替代engine.Execute,并通过await等待异步脚本执行完成
  2. 将脚本逻辑包裹在自执行的异步函数中,确保await request.getAsync(...)能正确等待异步请求完成

额外优化建议

  • 实际项目中建议复用HttpClient单例,避免频繁创建实例导致的socket资源耗尽问题
  • 可以考虑给Request类添加异步方法的错误处理逻辑,避免未捕获异常导致脚本执行失败

内容的提问来源于stack exchange,提问作者Matt Spinks

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 01:41:02