Initially I was going with Grayson's solution, but this
=IF(IFERROR(A1)<>0, A1, GOOGLEFINANCE(...))
Places a FALSE on the cell until the result is placed.
I needed that to be empty, i.e. "" as whatever different from that (cell <>"")
would trigger another cell to do another query/request.
I also needed the formula to be run depending on the trigger (the url in another cell). In this formula, if the trigger is placed after the formula has run, it won't trigger it.
So I have something like
=IF(AND(IFERROR(E53)<>0,E53<>""),E53, if(D53<>"",IMPORTDATA(D53),""))
<Update 2022-11>
While using this in arrayformula I noticed something that could be wrong.
IFERROR(E53)<>0 # Doesn't make sense.
It should be
NOT(ISERROR(E53))
And the whole thing in arrayformula (careful with AND/OR )
=ARRAYFORMULA( IF( NOT(ISERROR(E2:E)) * (E2:E<>"") ,E2:E, 'SOMETHING ELSE' ) )
I leave both versions in case someone spots errors in any of them.
<End of update 2022-11>
Explanation (It took me a while to understand it, so I could extend it):
D53 = myself
If I am nothing ("") or I am in Error (importdata not yet completed)
then
I am the result of -> If(D53<>"",IMPORTDATA(D53),"")
Which is:
If the cell before me is something different from "", run the importdata
with that cell as url, otherwise I am "" (nothing)
This achieves the goal of running the formula only once if the trigger is valid (the url on the cell before is there). Once the result is placed, it won't change.
If for whatever reason you need it to run again, you have to remove the formula and place it again.
Notes: If cellX has the result of an external fetch (IMPORTDATA for example) and on cellY=cellX, while on cellX you see "Loading ..." on cellY you will see a 0
(zero). I believe that explains why the other solution was comparing with 0.