B4J Question When do you ws.Flush

TomDuncan

Active Member
Licensed User
Longtime User
I am writing a web server.
I have many ..
B4X:
WebUtils.RedirectTo(ws, "admin_login")

call in *_click routines

What is the rule for using ws_flush

Thanks in advance.
Tom
 

EnriqueGonzalez

Well-Known Member
Licensed User
Longtime User
Hi in my experience (that includes studying the source code) you flush when you want to send the data to the browser.

If you usually just send one instruction you can flush right away.

It doesn't matter that you flush when you don't need too. the code prevents sending info if the buffer is empty.
 
Upvote 0

tchart

Well-Known Member
Licensed User
Longtime User
I have previously used it to write a partial page to show a loader/spinner icon while the rest of the page is generated.
 
Upvote 0

alwaysbusy

Expert
Licensed User
Longtime User
There is no general rule. In writing ABM, I've searched for a good balance when to do it. ws.flush means doing a round-trip to from your server to your browser, so you have to be careful not to do it to frequent.

e.g.
When adding (injecting) multiple html controls, I ws.flush after I've added all of them and not after each of them.
When running some javascript, I do it immediately
When filling a table, I do it in a batch (e.g. after having added every 50 rows)

The reason for that last one is because a WebSocket message has a limit to its size. e.g. adding all 1000 rows in one batch would probably cause a maxsize exceeded error.

What you want is for the user to have the best/fastest experience possible.

I don't know how your RedirectTo looks like, but it probably is some javascript your run like ws.Eval("window.location = arguments[0]", Array As Object(TargetUrl))
In that case I would do the ws.flush immediately after the eval.

Alwaysbusy
 
Upvote 0

Erel

B4X founder
Staff member
Licensed User
Longtime User
The reason for that last one is because a WebSocket message has a limit to its size. e.g. adding all 1000 rows in one batch would probably cause a maxsize exceeded error.
This shouldn't happen. The WebSocket should be flushed automatically in this case.
It is also flushed automatically at the end of a client -> server event and when you call Future.Value.
In other cases where the server sends data to the client, you must call flush yourself.

As written above nothing bad will happen if you call it when it is not really needed.

From performance point of view, the call to Future.Value is the important one. ws.Flush will not cause a round trip. It will asynchronously send the buffered data.

Future.Value pauses the WebSocket thread and causes it to wait for the value.
Bad code:
B4X:
Dim Value1 As String =Element1.GetVal.Value 'bad. Don't do it
Dim Value2 As String =Element2.GetVal.Value
Dim Value3 As String =Element3.GetVal.Value

Good code:
B4X:
Dim fv1 As Future =Element1.GetVal
Dim fv2 As Future =Element2.GetVal
Dim fv3 As Future =Element3.GetVal
'now you can get the values:
Log(fv2.Value) 'all three values will be available after a single server -> client -> server round trip.
 
Upvote 0

alwaysbusy

Expert
Licensed User
Longtime User
This shouldn't happen. The WebSocket should be flushed automatically in this case.
When building complex tables (with complex elements in cells), it is needed to flush logically now and then yourself. The WebSocket may flush in between as you say, but it results in bad formatted html (breaking inbetween open/close tags for example) being send to the browser, hence e.g. the append failing.

Doing it like this is the only way I could make it work reliable (simplified):
B4X:
dim s as String
for i = 0 to 50000
    s = s & "<tr><td>...</td><td>...</td><td>...</td><td>...</td></tr>"
    if i mod 50 then
        ws.eval("$('#myTable').append('" & s & "');", null)
        ws.flush
        s = ""
    end if    
next
 
Upvote 0
Top