Skip to content

Promises support

Please note

This documentation focuses on TMS FNC Cloud Pack promise-based methods. It does not serve as a general guide to using Promises in Delphi. If you're unfamiliar with Promises or need a deeper understanding of their usage, we recommend consulting the official Delphi-Promises library documentation.

Introduction

Promises support is currently rolling out. If you're working with a TMS FNC Cloud Component that does not yet support Promises, contact our support team by creating a feature request.

Promises allow developers to write sequential code instead of relying on events and nested callbacks, making asynchronous programming more intuitive and maintainable. This also opens up new possibilities that were previously not supported, such as requesting a new access token before executing a request.

Events vs promises

Events rely on event handlers that execute each time an event occurs successfully. This works well when the execution is independent, but as soon as one event depends on the result of another, managing multiple event handlers becomes complex. In some cases, the handler's behavior needs to change based on previous outcomes, adding even more complexity.

Promises, on the other hand, allow you to chain and await calls, making it easier to maintain clear and structured logic throughout execution.

procedure TForm1.btnClick(Sender: TObject);
begin
  TMSFNCCloudStorageServices1.GetFolderList;
end;

//In this area a lot of other code can take place
//In addition to that, GetFolderList can be called from multiple places,
//but always this event will be executed
//This makes the code not only hard to follow, but also hard to maintain

procedure TForm1.TMSFNCCloudStorageServices1GetFolderList(Sender: TObject;
  const AItems: TTMSFNCCloudItems;
  const ARequestResult: TTMSFNCCloudBaseRequestResult);
begin
  TMSFNCCloudDemoListBox1.BeginUpdate;
  TMSFNCCloudDemoListBox1.ItemIndex := -1;
  TMSFNCCloudDemoListBox1.Items.Clear;
  FillListBox(AItems, True, False);
  FillListBox(AItems, False, True);
  TMSFNCCloudDemoListBox1.EndUpdate;
end;
//Create our own GetFolderList logic that will always execute the same
//If we need to handle the result differently we can just create another 
//version of this
procedure TForm1.GetFolderList(AFolder: TTMSFNCCloudItem = nil);
begin
  TMSFNCCloudStorageServices1.GetFolderListPromise(AFolder)
  .Main.ThenBy(procedure (const AVoid: TVoid)
  begin
    if not FDestroying then //extra check: is the form currently being destroyed?
    begin
      TMSFNCCloudDemoListBox1.BeginUpdate;
      TMSFNCCloudDemoListBox1.ItemIndex := -1;
      TMSFNCCloudDemoListBox1.Items.Clear;
      FillListBox(TMSFNCCloudStorageServices1.PromiseFolderList, True, False);
      FillListBox(TMSFNCCloudStorageServices1.PromiseFolderList, False, True);
      TMSFNCCloudDemoListBox1.EndUpdate;
    end;
  end);
end;

Handling the results from a promise

The promises in TMS FNC Cloud Pack always return with a managed or reference counted type. Anything that should resolve in an object can be accessed via: - a property that is exposed by the control - the object that was passed as a parameter

The results reflect what are returned with events. The naming of the promise gives a hint of what to look for:

Promise Resulting object
TTMSFNCCloudGoogleGmail.GetLabelsPromise TTMSFNCCloudGoogleGmail.Labels
TTMSFNCCloudGoogleDrive.GetAccountInfoPromise TTMSFNCCloudGoogleDrive.Info
TTMSFNCCloudGoogleDrive.GetAttachment(AAttachment) AAttachment

In some cases we extended the controls with a separate object to give you access to the results as they were not available. These special properties are prefixed with Promise. Below you can find a list of them:

Promise Resulting object
GetFolderListPromise (all storage services) PromiseFolderList
GetFolderListHierarchicalPromise (all storage services) PromiseFolderList
Search*Promise (all storage services) PromiseSearch
CreateFolder (all storage services) PromiseCreateFolder
GetFileInfoPromise (Box, DropBox, Google Drive) PromiseFileInfo
GetFolderInfoPromise (Box, DropBox, Google Drive) PromiseFileInfo
Insert(AEntities) (StellarDS) PromiseInsertEntities

Fetch access token

All components that inherit from TTMSFNCCloudOAuth has access to the FetchAccessToken: IPromise<string> method. This allows to retrieve the latest valid access token. If the token is expired at the time of calling FetchAccessToken, it will automatically try to retrieve a new one using the refresh token. In case the refresh token is missing or invalid, it repeats the authorization process.

FetchAccessToken flow

Example: Using FetchAccesToken with ThenBy chaining

procedure TForm1.Button1Click(Sender: TObject);
begin
  TMSFNCCloudGoogleCalendar1.FetchAccessToken.ThenBy(procedure (const AValue: string)
  begin
    TMSFNCCloudGoogleCalendar1.GetCalendar('calendarID');
  end);
end;

Example: Using FetchAccessToken with Await

procedure TForm1.Button1Click(Sender: TObject);
begin
  TThread.CreateAnonymousThread(
  procedure
  begin
    TMSFNCCloudGoogleCalendar1.FetchAccessToken.Await;
    TMSFNCCloudGoogleCalendar1.GetCalendar('calendarID');
  end).Start;
end;