Difference between revisions of "pas2js AsyncAWait"

From Lazarus wiki
Jump to navigationJump to search
Line 15: Line 15:
  
 
An '''async''' procedure can contain multiple '''await''' calls.
 
An '''async''' procedure can contain multiple '''await''' calls.
 +
 +
==Example Async try fetch==
 +
 +
Example demonstrating waiting for an async function, catching errors with a try..except and no anonymous functions.
 +
 +
<syntaxhighlight lang="pascal">
 +
// Translated from https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Asynchronous/Async_await
 +
program askmom;
 +
 +
{$mode objfpc}
 +
 +
uses
 +
  browserconsole, JS, Web, SysUtils;
 +
 +
procedure myFetch; async;
 +
var
 +
  response: TJSResponse;
 +
  myBlob: TJSBlob;
 +
  image: TJSHTMLImageElement;
 +
  objectURL: string;
 +
begin
 +
  try
 +
    response := await(window.fetch('test1.png'));
 +
 +
    if not response.ok then
 +
      raise Exception.Create('HTTP error! status: '+str(response.status))
 +
    else begin
 +
      myBlob := await(response.blob());
 +
      objectURL := URL.createObjectURL(myBlob);
 +
      image := TJSHTMLImageElement(document.createElement('img'));
 +
      image.src := objectURL;
 +
      document.body.appendChild(image);
 +
    end;
 +
  except
 +
    console.log(JSExceptValue);
 +
  end;
 +
end;
 +
 +
begin
 +
  myFetch;
 +
end.
 +
</syntaxhighlight>
  
 
==Example Wait 2 Seconds==
 
==Example Wait 2 Seconds==

Revision as of 21:10, 27 May 2020

Overview

Pas2js supports the JS operators async/await to simplify the use of Promise, which itself simplifies writing asynchronous code, like starting a download, waiting for the result, then depending on the result start the next and so forth. Instead of writing a tedious and hard to read mass of sub functions an async procedure can be written in the common serial aka imperative way.

AWait

Pas2js provides a built-in await function, which supports three flavours:

function await(AsyncFunctionOfResultTypeT): T;
function await(aType; p: TJSPromise): aType; // explicit promise requires the resolved type
function await(const Expr: T): T; // implicit promise

The await function can only be used inside a procedure with the async modifier.

An async procedure can contain multiple await calls.

Example Async try fetch

Example demonstrating waiting for an async function, catching errors with a try..except and no anonymous functions.

// Translated from https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Asynchronous/Async_await
program askmom;

{$mode objfpc}

uses
  browserconsole, JS, Web, SysUtils;

procedure myFetch; async;
var
  response: TJSResponse;
  myBlob: TJSBlob;
  image: TJSHTMLImageElement;
  objectURL: string;
begin
  try
    response := await(window.fetch('test1.png'));

    if not response.ok then
      raise Exception.Create('HTTP error! status: '+str(response.status))
    else begin
      myBlob := await(response.blob());
      objectURL := URL.createObjectURL(myBlob);
      image := TJSHTMLImageElement(document.createElement('img'));
      image.src := objectURL;
      document.body.appendChild(image);
    end;
  except
    console.log(JSExceptValue);
  end;
end;

begin
  myFetch;
end.

Example Wait 2 Seconds

Program MyModule;

uses JS, Web;

function ResolveAfter2Seconds: TJSPromise;
// returns immediately with a Promise,
// which after 2 seconds gets resolved
begin
  Result:=TJSPromise.new(procedure(resolve, reject : TJSPromiseResolver)
    begin
    window.setTimeout(procedure
      begin
      resolve('resolved');
      end,
      2000); // wait 2 seconds
    end);
end;

procedure AsyncCall; async;
var s: string;
begin
  writeln('calling');
  s := await(string,resolveAfter2Seconds());
  // the await pauses this procedure returning to the caller
  // when the Promise from resolveAfter2Seconds gets resolved 
  // this procedure is continued
  writeln(s); // expected output: 'resolved'
end;

begin
  AsyncCall;
  // calling AsyncCall returns immediately, while the Promise is waiting
  writeln('called');
end.

Expected output:

calling
called
resolved