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

Power Query延迟递归异常:二次Endpoint轮询调用未执行求助

Power Query递归重试未执行的问题排查与解决

兄弟,我刚看完你的Power Query代码,完全懂你遇到的糟心事——明明写了递归逻辑要等结果就绪后重试,结果Fiddler只抓到一次第二个端点的请求,之后数据加载就卡着不动了对吧?这问题其实是Power Query的两个特性在“搞鬼”,咱们一步步拆解:

问题根源

1. 惰性求值导致递归未触发

你在else分支里写的Function.InvokeAfter(()=>@getResult(url),#duration(0,0,0,5)),本质上只是定义了一个「延迟执行的任务」,但Power Query是惰性求值的——它只会在真正需要结果的时候才去运行代码。这里你返回的是一个待执行的函数对象,而不是递归调用的结果,所以流程直接卡在这,不会继续触发重试。

2. Web.Contents默认缓存坑

就算你解决了惰性求值的问题,还有个隐藏坑:Web.Contents默认会缓存请求结果。如果第一次返回“未就绪”,第二次请求会直接用缓存的旧结果,Fiddler根本看不到新请求,等于重试白做了。

修复方案

针对这两个问题,咱们修改代码就行:

1. 让延迟后的递归立即执行

把else分支的代码改成Value.Invoke(Function.InvokeAfter(() => @getResult(url), #duration(0, 0, 0, 5)), {})——Value.Invoke会强制触发延迟后的函数执行,而不是返回函数本身,这样就能正常递归重试了。

2. 禁用Web.Contents缓存

在调用第二个端点的Web.Contents参数里加上CacheDuration = #duration(0, 0, 0, 0),确保每次请求都是全新的,不会用缓存的旧状态。

完整修复后的代码

let
    apikey = "MYAPIKEY",
    proxyendpoint = "URL OF THE FIRST ENDPOINT",
    bytesbody = File.Contents("FILE TO POST"),
    headers = [#"Ocp-Apim-Subscription-Key" = apikey],
    bytesresp = Web.Contents(proxyendpoint, [Headers=headers, Content=bytesbody]),
    jsonresp = Json.Document(bytesresp),
    opLoc = jsonresp[OperationLocation],
    getResult = (url) => let
        linesBody = Web.Contents(url, [
            Headers=headers,
            CacheDuration = #duration(0, 0, 0, 0) // 禁用缓存,确保每次请求都是新的
        ]),
        linesJson = Json.Document(linesBody),
        resultStatus = linesJson[status],
        linesData = if (resultStatus = "Succeeded") then
            linesJson[recognitionResult][lines]
        else
            Value.Invoke(Function.InvokeAfter(() => @getResult(url), #duration(0, 0, 0, 5)), {}) // 延迟后立即执行递归
    in linesData,
    linesText = List.Transform(getResult(opLoc), each _[text]),
    table = Table.FromList(linesText)
in table

进阶优化:加重试次数上限

为了避免无限递归(比如API一直返回未就绪),建议给递归加个重试次数限制,比如默认重试10次,到次数就抛出错误:

getResult = (url as text, optional retryCount as number) => let
    currentRetry = if retryCount = null then 10 else retryCount, // 默认重试10次
    linesBody = Web.Contents(url, [Headers=headers, CacheDuration = #duration(0,0,0,0)]),
    linesJson = Json.Document(linesBody),
    resultStatus = linesJson[status],
    linesData = if resultStatus = "Succeeded" then
        linesJson[recognitionResult][lines]
    else if currentRetry > 0 then
        Value.Invoke(Function.InvokeAfter(() => @getResult(url, currentRetry - 1), #duration(0,0,0,5)), {})
    else
        error "重试次数已达上限,结果仍未就绪"
in linesData

调用的时候用getResult(opLoc)(用默认10次)或者getResult(opLoc, 15)(指定15次)就行。

内容的提问来源于stack exchange,提问作者Akos Nagy

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 08:39:20