Oracle Apex动态操作:如何强制同步执行以避免竞争条件?
问题描述
我有一组页面项:
P1_ERRORS P1_ERROR_COUNT P1_RESULT
- 当
P1_ERRORS更新时,触发其变更动态操作(DA)计算P1_ERROR_COUNT。 P1_ERROR_COUNT的动态操作会根据错误计数将P1_RESULT设为“PASS”或“FAIL”。
另外还有页面项:
P1_IGNORE
- 当
P1_IGNORE设为“YES”时,其动态操作会清空P1_ERRORS,并将P1_RESULT设为“N\A”。
实际现象:P1_RESULT短暂变为“N\A”后又恢复为“PASS”。
原因:P1_IGNORE清空P1_ERRORS后,触发了P1_ERRORS的变更事件,重新计算P1_ERROR_COUNT为0,对应的动态操作又把P1_RESULT设为PASS,形成竞争条件。
虽然可以通过给部分动态操作设置客户端条件解决(但比较繁琐),请问是否有办法强制此类级联变更事件和动态动作同步执行?即DA1更新DA2后,等待DA2的动态操作触发完成再继续DA1的动作?
解决方法
针对Oracle APEX中这类动态操作的竞争问题,有几种更高效的同步执行方案:
1. 禁用目标项的事件触发,手动完成必要赋值
在P1_IGNORE的动态操作中,用JavaScript先禁用P1_ERRORS的change事件触发,避免后续DA自动执行,再手动完成所有必要的数值设置:
// 临时禁用P1_ERRORS的change事件,阻止触发对应的DA apex.event.delegate("#P1_ERRORS", "change", null, true); // 清空P1_ERRORS apex.item("P1_ERRORS").setValue(""); // 直接设置错误计数为0,跳过自动计算的DA apex.item("P1_ERROR_COUNT").setValue("0"); // 设置最终结果为N\A apex.item("P1_RESULT").setValue("N\\A"); // 恢复P1_ERRORS的change事件,不影响后续正常操作 apex.event.delegate("#P1_ERRORS", "change", null, false);
这种方式直接跳过了引发竞争的DA触发逻辑,逻辑清晰且无需修改其他动态操作。
2. 用Promise监听DA执行完成,确保顺序执行
如果需要保留原有DA的逻辑,可通过Promise包装操作,等待依赖DA执行完成后再继续:
将P1_IGNORE的动态操作拆分为两个步骤:
- 第一步:执行JavaScript代码:清空
P1_ERRORS并监听P1_ERROR_COUNT的变化,完成后返回Promise
return new Promise((resolve) => { // 清空P1_ERRORS,触发后续DA apex.item("P1_ERRORS").setValue(""); // 监听P1_ERROR_COUNT的change事件,确认DA执行完成 const countChangeListener = () => { resolve(); document.querySelector("#P1_ERROR_COUNT").removeEventListener("change", countChangeListener); }; document.querySelector("#P1_ERROR_COUNT").addEventListener("change", countChangeListener); });
- 第二步:设置P1_RESULT为"N\A":将此步骤的「执行时机」设置为「JavaScript代码返回成功」,确保在
P1_ERROR_COUNT的DA执行完成后再覆盖结果。
3. 给竞争DA添加单一条件阻断执行
在P1_ERROR_COUNT对应的动态操作中,添加一个客户端条件:仅当P1_IGNORE不为"YES"时才执行。
条件表达式:
apex.item("P1_IGNORE").getValue() !== "YES"
这种方式仅需修改一处DA的条件,就能阻断P1_IGNORE触发时的竞争逻辑,比给多个DA加条件更简洁。
内容的提问来源于stack exchange,提问作者smackenzie
相关产品推荐
相关产品推荐

