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

Progress ABL如何捕获UI事件触发错误并传递至主程序块

UI事件触发的错误透传到主块捕获方案

问题描述

在Progress ABL程序中存在如下场景:

  • F6按键事件负责更新ttnom临时表数据
  • fill_tt过程执行时如果检测到临时表为空,会抛出PROGRESS.lang.apperror('Temp-table is empty')异常
    需要确认是否可以让该异常从F6事件处理逻辑透传到程序主块,被主块的CATCH块捕获,而非在事件内部被拦截处理。

对应示例代码如下:

BLOCK-LEVEL ON ERROR UNDO, THROW.

DEFINE VARIABLE inomtr AS i NO-UNDO.
DEFINE VARIABLE lexit AS L NO-UNDO.

DEFINE TEMP-TABLE ttnom NO-UNDO 
  FIELD uid AS int64
INDEX idx1 IS unique uid.  

DEFINE FRAME fupd
SKIP(1)
inomtr FORMAT '>>>>>>>>>>>>9' NO-LABEL
SKIP(1)
WITH VIEW-AS DIALOG-BOX SIDE-LABELS.

 ON GO OF FRAME fupd
 DO:
   _t1:
   DO ON ERROR UNDO, RETURN NO-APPLY: 
     ASSIGN inomtr.
     IF CAN-FIND (FIRST ttnom NO-LOCK WHERE ttnom.uid = inomtr) THEN 
         LEAVE _t1.
     MESSAGE 'inomtr not found' VIEW-AS ALERT-BOX.
     RETURN NO-APPLY.    
   END.   
 END.
 
ON F3 OF inomtr IN FRAME fupd
DO:
  RUN choose_nom(OUTPUT inomtr).
END.

ON F6 of FRAME fupd ANYWHERE 
DO:
  DO ON ERROR UNDO, THROW  :
     RUN fill_tt.
     CATCH ERROR AS PROGRESS.lang.error:
        message error:GetMessage(1) + return-value VIEW-AS ALERT-BOX.
        lexit = YES.
        STOP.
     END CATCH.
  END.
  RETURN NO-APPLY.
END.

 
_tr:
DO ON ERROR UNDO, THROW
   ON STOP UNDO, LEAVE
   ON ENDKEY UNDO, LEAVE:

  RUN fill_tt.    
  DO WHILE TRUE ON ERROR UNDO, throw
                ON STOP UNDO , RETRY 
                ON ENDKEY UNDO , RETRY :
     IF RETRY OR lexit = yes THEN 
        DO:
          IF lexit = NO THEN 
             MESSAGE 'Exit?' VIEW-AS ALERT-BOX BUTTONS YES-NO UPDATE lexit.
          IF lexit = YES THEN 
             LEAVE _tr.    
        END.          
     DISPLAY  WITH FRAME fupd.
     ENABLE inomtr WITH FRAME fupd.

     WAIT-FOR GO OF FRAME fupd.

     RUN do_nomtr(inomtr).         
  END. 
  CATCH ERROR AS PROGRESS.lang.error:
     message ERROR:GetMessage(1) + RETURN-VALUE VIEW-AS ALERT-BOX.
  END CATCH.  
END.

PROCEDURE do_nomtr:
   DEFINE INPUT PARAM inomtr AS i NO-UNDO.

   MESSAGE inomtr VIEW-AS ALERT-BOX.
END PROCEDURE.

PROCEDURE fill_tt:
  DO ON ERROR UNDO, THROW:
     DISPLAY 'Loading temp-table' WITH FRAME ftt VIEW-AS DIALOG-BOX.
     EMPTY TEMP-TABLE ttnom.
     FOR EACH link NO-LOCK WHERE link.type = 3 AND link.class-code = '1B' AND 
                                 link.file-name = 'r-goods' AND link.arch = no ON ERROR UNDO, THROW:
                IF CAN-FIND(FIRST ttnom WHERE ttnom.uid = link.link-num) THEN 
                   NEXT.
                CREATE ttnom.
                ASSIGN ttnom.uid = link.link-num.                
     END.                                             

     HIDE  FRAME ftt NO-PAUSE.
     IF NOT TEMP-TABLE ttnom:HAS-RECORDS THEN 
        UNDO, THROW NEW PROGRESS.lang.apperror('Temp-table is empty').
  END.
END PROCEDURE.

核心结论

ABL的UI事件触发器运行在独立的UI消息循环调用栈上,原生不支持异常自动跨栈透传到WAIT-FOR所在的主块,但可以通过错误暂存+主动重抛的方式实现需求。原代码无法透传的原因有两个:

  • F6事件块内部直接写了CATCH块拦截异常,且在块内执行STOP语句直接终止了错误传播流程
  • 事件触发的调用栈和主块调用栈隔离,未捕获的事件异常默认会被UI运行时拦截,不会自动传到主块的CATCH

改造步骤

  • 新增模块级错误变量,用于暂存事件处理过程中产生的异常
    DEFINE VARIABLE oEventError AS Progress.Lang.Error NO-UNDO.
    
  • 改造F6事件块,移除内部直接弹框、STOP的处理逻辑,捕获异常后暂存到变量,标记退出状态即可
    ON F6 of FRAME fupd ANYWHERE 
    DO:
      DO ON ERROR UNDO, THROW  :
         RUN fill_tt.
         CATCH err AS PROGRESS.lang.error:
            oEventError = err.
            lexit = YES.
         END CATCH.
      END.
      RETURN NO-APPLY.
    END.
    
  • 在主块WAIT-FOR语句执行完成后,立刻检查暂存的错误对象,如果存在有效错误则主动抛出,异常就会被主块的CATCH块统一捕获处理
    WAIT-FOR GO OF FRAME fupd.
    /* 主动重抛事件处理中产生的异常 */
    IF VALID-OBJECT(oEventError) THEN DO:
      UNDO, THROW oEventError.
    END.
    
    RUN do_nomtr(inomtr).
    

注意事项

  • 不要在事件处理的CATCH块中使用STOP、RETURN ERROR这类会直接终止事件上下文的语句,否则异常会丢失
  • 如果需要统一处理多个UI事件的错误,只需要让所有事件的CATCH块都把异常赋值给同一个oEventError变量即可
  • 不要尝试给WAIT-FOR语句加ON ERROR UNDO, THROW来捕获事件异常,该配置仅能捕获WAIT-FOR语句本身的错误,无法捕获其派发的事件触发器内抛出的错误

内容的提问来源于stack exchange,提问作者Александр Овчинников

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.03 04:33:26