Blog

All Blog Posts  |  Next Post  |  Previous Post

Diving deeper: Cloudbase REST in Delphi, Part 3/3: Sync vs Async

Bookmarks: 

Thursday, October 6, 2022

TMS Software Delphi  Components

Intro

Today, we are continuing our cloud base REST blog series with part 3: Sync vs Async. If you missed our first blog, follow this link: https://www.tmssoftware.com/site/blog.asp?post=993. The second blog covers a couple of special cases and can be found here: https://www.tmssoftware.com/site/blog.asp?post=996. TMS FNC Core is a universal core layer for creating rich visual and non-visual components for VCL, FMX, LCL and WEB core apps. A major part of TMS FNC Core is the ability to create and execute REST requests. In this blog post we will take a look at the difference between sync and async when handling REST requests and responses.

Async

By default, each request created and executed is being processed asynchronously. This means that whenever you are calling

c.ExecuteRequest(
  procedure(const ARequestResult: TTMSFNCCloudBaseRequestResult)
  begin
 
  end
  );

The code will not block the caller and proceed with executing code. The request is being prepared and executed in a different thread. We can test this by adding some log statements to our original GET request.

c.Request.Clear;
c.Request.Host := 'https://httpbin.org';
c.Request.Method := rmGET;
c.Request.Path := '/get';

Memo1.Lines.Add('Before executing request');
c.ExecuteRequest(
  procedure(const ARequestResult: TTMSFNCCloudBaseRequestResult)
  begin
    Memo1.Lines.Add('Request finished');
  end
  );
Memo1.Lines.Add('Next Code');
The code will output the following lines

Before executing request
Next Code
Request finished
As you can see, "Before executing request" is being logged first. Then the second line is "Next Code", because the ExecuteRequest starts a thread and awaits the results from the service. Depending on the service this might take a while, or it could also very well be that "Request finished" is triggered before "Next Code", but this is unreliable. In most cases "Request finished" will be triggered after "Next Code". The benefit of using this code is that lengthy operations such as uploading a file, or retrieving/posting data from/to a service will not block the main thread of your application and will keep it responsive.

Sync

Downloading significant amounts of data such as files or larger strings, or even when working with a slower service, async benefits from allowing multiple requests being executed. In some cases however, to benefit code flow, it's better to use a synchronous call. For smaller requests such as geocoding or reverse geocoding or retrieving user information a synchronous call can help executing, processing and continuing the code with the retrieved data. Of course, the downside is that the main thread of your application is blocked. Applying this on our original code, we change it to 

var
  r: TTMSFNCCloudBaseRequestResult;
begin
  c.Request.Clear;
  c.Request.Host := 'https://httpbin.org';
  c.Request.Method := rmGET;
  c.Request.Path := '/get';

  Memo1.Lines.Add('Before executing request');
  r := c.ExecuteRequest(nil, nil, false);
  if Assigned(r) and r.Success then
    Memo1.Lines.Add('Request finished');
  Memo1.Lines.Add('Next Code');
end;
Note that ExecuteRequest has 3 parameters: The callback, a progress event and a boolean parameter to decide if the request is applying synchronous or asynchronous processing. We can keep the original code with the callback, or we can now execute the request and turn it into a function, by specifying false as the last parameter, making it a synchronous call. The result is that the memo lines are now in the following order
Before executing request
Request finished
Next Code

"Sync" in TMS WEB Core

As TTMSFNCCloudBase is cross-platform, executing REST request are also available in a TMS WEB Core application. The asynchronous implementation doesn't require any additional code, as by default, the code that runs in your browser runs asynchronously and the result is captured in a callback. Now, to make this a "synchronous" request, which in web terms means that the code will await the result in it's own scope, we'll need to apply the async/await methodology (https://javascript.info/async-await). Code that runs outside of the scope of the function that is awaiting the result will continue to run. This is a significant difference with all other platforms. When we have a piece of REST request code in a specific function/procedure and need to await the result of the request we need to add the [async] attribute to our function/procedure definition. For this sample, we added a button, which has a click event handler.

type
  TForm1 = class(TWebForm)
    WebButton1: TWebButton;
    [async]
    procedure WebButton1Click(Sender: TObject);
  private
    { Private declarations }
    c: TTMSFNCCloudBase;
  public
    { Public declarations }
  end;
The code inside the event handler implementation uses the await functionality. Note that TTMSFNCCloudBase ExecuteRequest function is prepared to handle await. To apply this to our original request we get the following code
procedure TForm1.WebButton1Click(Sender: TObject);
var
  r: TTMSFNCCloudBaseRequestResult;
begin
  c.Request.Clear;
  c.Request.Host := 'https://httpbin.org';
  c.Request.Method := rmGET;
  c.Request.Path := '/get';

  WebMemo1.Lines.Add('Before executing request');
  r := await(TTMSFNCCloudBaseRequestResult, c.ExecuteRequest(nil, nil, false));
  if Assigned(r) and r.Success then
    WebMemo1.Lines.Add('Request finished');
  WebMemo1.Lines.Add('Next Code');
end;
Executing this will give us the same result as executing this method in a synchronous implementation on the other platforms. Remember that this specific implementation will not block the main browser thread.

Video

Below is a video explaining the difference between synchronous and asynchronous operations in TTMSFNCCloudBase, and how to execute simple GET requests.


Feedback

Although this might seem repetitive to see the keyword "Feedback" on every blog post, we greatly appreciate feedback. This only helps us improving our products. Want to know more about registring your own component based on TTMSFNCCloudBase, or even integrate authentication? Visit the following link to learn more: https://download.tmssoftware.com/doc/tmsfnccloudpack/gettingstarted/overview/





Pieter Scheldeman


Bookmarks: 

This blog post has received 2 comments.


1. Thursday, October 6, 2022 at 8:18:39 PM

Await is unknown. Which unit contains this function
[dcc32 Error]: E2003 Undeclared identifier: ''await''


Brian Knudsen


2. Thursday, October 6, 2022 at 8:20:39 PM

I see you use DCC32 which is used for VCL or FMX project.
But the await feature is for a TMS WEB Core project.

Bruno Fierens




Add a new comment

You will receive a confirmation mail with a link to validate your comment, please use a valid email address.
All fields are required.



All Blog Posts  |  Next Post  |  Previous Post