@Command vs @PostedCommand:為什麼你的公式沒照順序跑
你在按鈕公式裡想「先把欄位算好、再叫 UI 執行一個動作」,寫下來卻發現:動作先跑了、你的算式後跑,順序整個顛倒。或者你把一個 @PostedCommand 放在公式最上面,它偏偏最後才動。
這不是 bug,是 Formula 的執行順序規則——@Command 跟 @PostedCommand 的時機不一樣,而且有些 @Command 本身就被延後。搞不清楚這條,UI 動作的先後就會不如預期。
重點摘要
- 基本規則:Domino 從上到下、左到右評估公式,做完一句才做下一句——但
@PostedCommand和少數@Command是例外,它們排到所有 @function 都跑完之後才執行。 @Command:大致「依序執行」(with some exceptions)。@PostedCommand:一律排到最後、彼此之間照順序跑。所以寫在公式最前面的@PostedCommand,反而最後才動——官方說這是在「模擬 R3 時代 @Command 的行為」。- 有些
@Command天生就 deferred:官方 @Command 參考頁有張表把命令分成「Evaluated after all @functions」(如EditClear/FileExit/NavigateNext)與「Evaluated immediately」(如Clear/ExitNotes/NavNext)。名字很像、時機不同,別搞混。 - 實務:要「先算好、再動 UI」→ 動作用
@PostedCommand;要「立刻切狀態再繼續往下」→@Command。
兩者的執行時機
官方 Order of evaluation 把總規則寫得很清楚:
Domino evaluates formulas from beginning to end and left to right, completing each statement before proceeding to the next, except that @PostedCommand and a few @Command functions are executed in order after all other @functions complete execution.
而 Working with @commands 分別定義兩者:
@Command:「@Command functions execute in sequence with other @functions, with some exceptions.」@PostedCommand:「@PostedCommand functions execute in sequence with each other after all other @functions execute.」——並註明「This emulates the behavior of @Command in Notes R3.」
「寫在最前面卻最後跑」
@PostedCommand 最反直覺的一點:它在原始碼裡的位置不代表執行順序。官方的例子:
@PostedCommand([CommandName]; Argument);@If(Condition; TrueStatement; FalseStatement);FIELD X := "Text"官方對這段的註解是:「The first statement is executed last.」——第一句(那個 @PostedCommand)最後才執行,因為它要等 @If、FIELD X := 這些 @function 全跑完。
對照 @Command,同樣寫在前面就先跑:@Command([EditDocument]) 會在後面的 @Prompt 之前執行;換成 @PostedCommand([EditDocument]) 就會在 @Prompt 之後。這一前一後,常常就是「文件還沒進編輯模式、prompt 就先跳出來」這種 bug 的根源。
有些 @Command 本來就是 deferred
這是最容易被忽略的一層:不是所有 @Command 都「立刻執行」。@Command 參考頁那張表把命令分成兩類——
- Evaluated after all @functions(等所有 @function 跑完才執行,行為等同 @PostedCommand):例如
EditClear、FileExit、NavigateNext。 - Evaluated immediately(立刻執行):例如
Clear、ExitNotes、NavNext。
注意上面兩兩對照的名字有多像(FileExit vs ExitNotes、NavigateNext vs NavNext)。挑錯一個,執行時機就差一整輪。要精準控制順序時,先查你用的那個命令屬於哪一類,別憑名字猜。
該用哪個
- 要「先把欄位算好、判斷做完,再執行 UI 動作」 → 動作用
@PostedCommand。這樣它保證在你的計算之後才動。 - 要「立刻切換狀態,再接著往下做」(例如先進編輯模式,再根據模式做別的) → 用
@Command,讓它當下就執行。 - 多個動作要有明確先後 → 全部用
@PostedCommand,它們之間會照書寫順序跑;混用@Command與@PostedCommand,順序就會裂成「immediate 的先、posted 的後」兩批。
同類別在其他語言
@Command/@PostedCommand 是 Formula 語言驅動 Notes 前端 UI 的機制,沒有直接的 Java/SSJS class 對應:
- LotusScript:對應的是
NotesUIWorkspace的方法(EditDocument、ViewRefresh等)——直接呼叫、直接執行,沒有 @PostedCommand 那種「排到最後」的語意,順序就是你呼叫的順序。 - SSJS/XPages:沒有
@Command。前端動作走 XPages 自己的事件與 partial refresh 模型,不是這套 posted/immediate 的排程。