sábado, 12 de novembro de 2016

Static JSON in Smart Mobile Studio

A tidy solution for using static JSON data in Smart Mobile Studio

I wanted to use JSON to store some some static data. I could have a separate .js file that holds my JSON data as an object - but this seems messy.

Since most browsers support JSON.parse(), which is defined in ECMA-JSON unit, we can declare any JSON string in SmartMS, and you can always use the JSON.parse method to get the JSON object.

AJAX seems a bit overkill - it just needs to evaluate it at run-time, nothing is dynamic. You can declare this JSON string in global constants or variables. In this experiment I will declare in the class scope using it in a private field, class const, class var and in a const

type
  TForm1 = class(TW3Form)
  private
    { private declarations }
    OBJ_CLASS: variant    = '{"employees":[{"id":1,"firstName":"smart","lastName":"mobilestudio"}]}';
    class Const OBJ_CONST = '{"employees":[{"id":1,"firstName":"smart","lastName":"mobilestudio"}]}';
    class var OBJ_VAR     = '{"employees":[{"id":1,"firstName":"smart","lastName":"mobilestudio"}]}';
    Const OBJCONSTANT     = '{"employees":[{"id":1,"firstName":"smart","lastName":"mobilestudio"}]}';
  protected
    { protected declarations }
  end;

implementation

Const GLOBALOBJCONST      = '{"employees":[{"id":1,"firstName":"smart","lastName":"mobilestudio"}]}';
var GLOBALOBJVAR: variant = '{"employees":[{"id":1,"firstName":"smart","lastName":"mobilestudio"}]}';

The functionally class vars in Smart Pascal work like class-scoped global variables, i.e. their lifetime is global and there is only one copy of the variable per declaration. Indeed, before having access to proper class variables, most Delphi programmers would use a global variable hidden in the implementation section of the unit that declares the class instead. 

  {* Using private Class var *}
  var obj3 := JSON.Parse(OBJ_VAR);
  WriteLn(obj3.employees[0]);

  var obj4 := JSON.Parse(OBJ_VAR);
  WriteLn(obj4.employees[0]);

  {*----- Using global var ---------*}
  var obj7 := JSON.Parse(GLOBALOBJVAR);
  WriteLn(obj7.employees[0]);

  var obj8 := JSON.Parse(GLOBALOBJVAR);
  WriteLn(obj8.employees[0]);

This is recommended way, there's just one copy the JSON string through the main js file.

{ main.js }
obj3 = JSON.parse(OBJ_VAR);
WriteLn(obj3.employees[0]);
obj4 = JSON.parse(OBJ_VAR);
WriteLn(obj4.employees[0]);

obj7 = JSON.parse(GLOBALOBJVAR);
WriteLn(obj7.employees[0]);
obj8 = JSON.parse(GLOBALOBJVAR);
WriteLn(obj8.employees[0]);

{ global application scope }
var OBJ_VAR = "{\"employees\":[{\"id\":1,\"firstName\":\"smart\",\"lastName\":\"mobilestudio\"}]}";
var GLOBALOBJVAR = "{\"employees\":[{\"id\":1,\"firstName\":\"smart\",\"lastName\":\"mobilestudio\"}]}";

Class const - a constant value is associated with the class itself and not an instance of the class, this will also work like global const but you can have more than one copy of the JSON string per declaration.

For instance. let say you declare several objects that use the same JSON object, and you have declared the JSON string in a const or class const

  {*--- Using private Class Const ---*}
  var obj1 := JSON.Parse(OBJ_CONST);
  WriteLn(obj1.employees[0]);

  var obj2 := JSON.Parse(OBJ_CONST);
  WriteLn(obj2.employees[0]);

  {*----- Using global Const ----------*}
  var obj5 := JSON.Parse(GLOBALOBJCONST);
  WriteLn(obj5.employees[0]);

  var obj6 := JSON.Parse(GLOBALOBJCONST);
  WriteLn(obj6.employees[0]);

  {*----- Using private Const ---------*}
  var obj11 := JSON.Parse(Self.OBJCONSTANT);
  WriteLn(obj11.employees[0]);

  var obj12 := JSON.Parse(Self.OBJCONSTANT);
  WriteLn(obj12.employees[0]);

There is is a drawback, a lot of repetitive JSON string will be emitted in the main JS file.

{ main.js }
  obj1 = JSON.parse("{\"employees\":[{\"id\":1,\"firstName\":\"smart\",\"lastName\":\"mobilestudio\"}]}");
  WriteLn(obj1.employees[0]);
  obj2 = JSON.parse("{\"employees\":[{\"id\":1,\"firstName\":\"smart\",\"lastName\":\"mobilestudio\"}]}");
  WriteLn(obj2.employees[0]);

  obj5 = JSON.parse("{\"employees\":[{\"id\":1,\"firstName\":\"smart\",\"lastName\":\"mobilestudio\"}]}");
  WriteLn(obj5.employees[0]);
  obj6 = JSON.parse("{\"employees\":[{\"id\":1,\"firstName\":\"smart\",\"lastName\":\"mobilestudio\"}]}");
  WriteLn(obj6.employees[0]);

  obj11 = JSON.parse("{\"employees\":[{\"id\":1,\"firstName\":\"smart\",\"lastName\":\"mobilestudio\"}]}");
  WriteLn(obj11.employees[0]);
  obj12 = JSON.parse("{\"employees\":[{\"id\":1,\"firstName\":\"smart\",\"lastName\":\"mobilestudio\"}]}");
  WriteLn(obj12.employees[0]);   

If we store the JSON string in a private field, there's one copy per declaration as well, we get the expected result, the json string will be stored in class scope.

var TForm1 = {
   $ClassName:"TForm1",$Parent:TW3Form
   ,$Init:function ($) {
      TW3Form.$Init($);
      $.OBJ_CLASS = "{\"employees\":[{\"id\":1,\"firstName\":\"smart\",\"lastName\":\"mobilestudio\"}]}";
   }
   /// procedure TForm1.InitializeForm()
   ,InitializeForm:function(Self) {
      TW3CustomForm.InitializeForm(Self);
   }
   /// procedure TForm1.InitializeObject()
   ,InitializeObject:function(Self) { ...} 


JS resource approach

You can kind-of simulate by using global variables (all derived classes, units and forms will share the same variable) using the JS resource approach. Under Project Manager, right click at Resources, choose New... Javascript.Just declare some variable (the resource name for instance) to store some raw javascript as the JSON object:

var JS1 = {
 "employees" : [{
   "id" : 1,
   "firstName" : "smart",
   "lastName" : "mobilestudio"
  }]}

Under the implementation session, declare an external property such as:

function data: variant; external 'JS1' property;

IMHO, this would be the most natural syntax I came across, I'm accessing the pure JSON object :)

  var obj13 := data.employees[0];
  WriteLn(obj13);

  var obj14 := data.employees[0];
  WriteLn(obj14);



segunda-feira, 5 de setembro de 2016

Flying Creatures with Smart


Smart Creatures

In this experiment, I'm going to show you how to use a texture atlas in Smart Mobile Studio, and create the flying sea creatures animations.
Here's an animation I re-created recently using a texture atlas:

Texture Atlas in Smart

I'm going to jump right into how to use a texure atlas for animations in Smart Mobile Studio, but I would say using an atlas is far superior to using a spritesheet.

Using Texture atlas allows you to:

a) Use more animations and sprites: Make your animation run smoother.
Not all frames have to be the same size when using an atlas.
When using an atlas each element is only drawn once. (a spritesheet is redrawn every frame)

b) Save memory: Compress your sprite sheet and drastically reduce memory usage. Reduce memory consumption, not image quality, it packs frame data more efficiently, and reduce memory and bandwidth.

c) Increase framerate: Compute frames faster and ... It's easier to refer to frames by name rather than by index.

d) Make your game start faster: For maximum performance directly export to your target system's image formats.

e) Preserve visual quality: The effect of compression or dithering is nearly invisible on high-resolution devices or moving objects.

Now a little more background on sprites-sheet and texture-atlas.
A sprites-sheet (often refers to a large image that) is supposed to contain the animation frames of a
specific 2d character or projectile in a game. You can almost think of it as the model of a 2d-character.
It stores all the various animations created for a specific character.

A texture-atlas (aka tile map, tile engine) is a large image containing a collection, or "atlas", of sub-images, each of which is a texture map for some part of a 2D or 3D model. The sub-textures can be rendered by modifying the texture coordinates of the object's map on the atlas, essentially telling it which part of the image its texture is in. You can think of these as 2d images "painted" over 3d objects.

Any 3D object (for example a weapon, a garbage can) or character can have a texture applied to it. Especially 3D levels may require multiple different textures for various walls and elements in the 3d scenery. All these textures can be contained accessibly and effectively in a single large image composed of many squares (subregions) devoted to a specific model.

In an application where many small textures are used frequently, it is often more efficient to store the textures in a texture atlas which is treated as a single unit by the graphics hardware.
This saves memory and because there are less rendering state changes by binding once, it can be faster to bind one large texture once than to bind many smaller textures as they are drawn.

Creating a Texture Atlas

I've been using the Texture Packer (this is a paid tool) to create the atlas, there are free tools out there, but in Texture Packer, you just drag 'n drop some pictures and the tool will just re-arrange all the sub-images into a big image.PNG file with a JSON file with the info that describles the coordinates (map) of where each picture begins and ends, it's lika HTML map. This is so nice!

We're going to load a single file (seacreatures.png) in SMS so you should place them both within the www/res folder. The .png file is probably pretty obvious, but let's take a look at the piece of this .json file. It's a very long file.

{
"frames" : [{
  "filename" : "blueJellyfish0000",
  "frame" : {
   "x" : 484,
   "y" : 770,
   "w" : 64,
   "h" : 64
  },
  "rotated" : false,
  "trimmed" : true,
  "spriteSourceSize" : {
   "x" : 0,
   "y" : 0,
   "w" : 66,
   "h" : 66
  },
  "sourceSize" : {
   "w" : 66,
   "h" : 66
  }
 }, {
  "filename" : "blueJellyfish0001",
  "frame" : {
   "x" : 484,
   "y" : 836,
   "w" : 63,
   "h" : 65
  },
  "rotated" : false,
  "trimmed" : true,
  "spriteSourceSize" : {
   "x" : 1,
   "y" : 0,
   "w" : 66,
   "h" : 66
  },
  "sourceSize" : {
   "w" : 66,
   "h" : 66
  }
 }, {
  "filename" : "blueJellyfish0002",
  "frame" : {
   "x" : 322,
   "y" : 1621,
   "w" : 62,
   "h" : 65
  },
  "rotated" : false,
  "trimmed" : true,
  "spriteSourceSize" : {
   "x" : 2,
   "y" : 0,
   "w" : 66,
   "h" : 66
  },
  "sourceSize" : {
   "w" : 66,
   "h" : 66
  }
 },{...}
],
"meta" : {
 "app" : "",
 "version" : "",
 "image" : "seacreatures.png",
 "format" : "RGBA8888",
 "size" : {
  "w" : 1024,
  "h" : 2048
 },
 "scale" : "1"
}
}

The important parts here are that it provides a name for a specific sprite and also provides the coordinates for where it is located in the image. We can refer to a specific sprite by it's frame name.
Basically, I'm going to use the "genFrameNames" function. This function will automatically create an array of names for you if they are in a JSON format. We don't want to write all these spritenames manually.

Of course, you could also just write this out manually if you want but when you've got an animation that's 20 frames long it certainly helps to speed up development and also makes your code look a lot cleaner.

In the creatures example, I'm going to use multi-animations.
For instance, I have 33 sprites that make up my blueJellyfish animation:
'blueJellyfish0000', 'blueJellyfish0001', 'blueJellyfish0002' ... 'blueJellyfish00032'

So rather than write all of these out manually, I use this:

animations.Add( TAnimation.create('jellyfish', genFrameNames('blueJellyfish', 0, 32, '', 4), 60) );

I supply 'jellyfish' as the prefix, and specify the start as 0 and end as 32 so it will generate the following array:
['blueJellyfish0000', 'blueJellyfish0001', 'blueJellyfish0002' ... 'blueJellyfish00032'];

Basically, I've created an array of records to store my animations, and create the sprites, according to the current frame. I ended up creating a function to get the current frame (getCurrentFrame).


JellyfishanimObj := animObj.createSprite( animations[0].getCurrentFrame);

Now, we can render this sprite anywhere:
JellyfishanimObj.draw(ctx, 670, 20);

I really like using the texture atlas approach you don't have to worry about making all of your sprites the same size and it makes it super easy to generate animations by referencing the names of the files using the "genFrameNames" function.

This is actually my swimming creatures animation with Smart, at least but you get the idea!

segunda-feira, 29 de agosto de 2016

Promise in Smart Mobile Studio

The traditional way to deal with asynchronous tasks in smart pascal are callbacks; call a method, give it a function reference to execute once that method is done. For example, say I want to run code asynchronous that:
a) fetch the person object, after half a second;
b) create the message;
c) change the message; and
d) display the message.


type
  TCallbackFn = procedure(d: variant; f: variant);

var person := JSON.parse('{"firstName": "Warley", "lastName":"Alex", "favoriteTeam":"Cruzeiro"}');

var api = CLASS
 getPerson := lambda(callback: TCallbackFn)
          w3_SetTimeout(lambda()
       callback(null, person);
    end, 500);
 end;

 getMessage := lambda(person: variant; callback: TCallbackFn)
   w3_SetTimeout(lambda()
     callback(null, person.firstName + ' ' + person.lastName + ' likes the ' + person.favoriteTeam);
   end, 500);
 end;

 mapMessage := lambda(message: variant): variant
     Result := message + ', the 2nd worst team in the Brazilian footbal league.';
 end;
END;

{ using callback approach }
api.getPerson(lambda(err, person)
  api.getMessage(person, lambda(err, message)
    console.log(api.mapMessage(message));
  end);
end);

{ Warley Alex likes the Cruzeiro, the 2nd worst team in the Brazilian footbal league.}

This is pretty neat, it is often much easier to read inline anonymous functions, as in the example. It will also spare you from having to find a name for all the callbacks. In such cases, using inline anonymous functions is even more preferable.
But, it has some drawbacks; for one, combining or chaining multiple asynchronous processes is tricky; it either leads to a lot of boilerplate code, or what's known as callback hell.

Callback hell is any code where the use of function callbacks in async code becomes obscure or difficult to follow. Generally, when there is more than one level of indirection, code using callbacks can become harder to follow, harder to refactor, and harder to test. A code smell is multiple levels of indentation due to passing multiple layers of function literals.

There is an alternative to dealing with asynchronous code in smart pascal: using Promises.

Promises are an alternative to callbacks for delivering the results of an asynchronous computation.
They require more effort from implementors of asynchronous functions, but provide several benefits for users of those functions. Promises help deal with the callback nesting and with the exception handling.

The Simplest Use Case
Let's begin our promise implementation as simple in Smart Mobile Studio.
Just create an unit and define this externals classes:

type
  JDeferred = class;
  TCallback = procedure(Value: Variant);
  TCallbackFn = procedure(d: variant; f: variant);
  TJDeferred_object_new_fn_ = function (d: TCallback): variant;
  TJDeferred_object_new_fn  = procedure (resolve: TCallback; reject: TCallback);
  TPromiseCallback = function(Value: Variant): Variant;
 TEventHandler = function(event: variant): Variant;

  JPromise = class external "Promise"
    constructor create(fn: TJDeferred_object_new_fn_{ = nil}); overload;
    constructor create(resolve: TJDeferred_object_new_fn_; reject: TJDeferred_object_new_fn_); overload;
    constructor create(fn: TJDeferred_object_new_fn); overload;
    function always(alwaysCallbacks: array of variant): JPromise;
    function done(doneCallbacks: array of variant): JPromise; overload;
    function done(doneCallbacks: variant): JPromise; overload;
    function fail(failCallbacks: array of variant): JPromise;
    function progress(progressCallbacks: array of variant): JPromise;
    function state(): string;
    function &then(doneCallbacks: variant; failCallbacks: variant = undefined; progressCallbacks: variant = undefined): JPromise;
    function &then(onFulfilled: TPromiseCallback = nil): JPromise; overload;
    function &then(onFulfilled: TPromiseCallback; onRejected: TPromiseCallback): JPromise; overload;
    function catch(rejectCallback: Variant = nil): JPromise; overload;
    function catch(rejectCallback: TPromiseCallback): JPromise; overload;
    class function promise(target: Variant): JPromise;
  end;

type
  JDeferred = class external "Promise"(JPromise)
    function notify(args: array of variant): JDeferred;
    function notifyWith(context: variant; args: array of variant): JDeferred;
    function reject(args: array of variant): JDeferred; overload;
    function reject(args: variant): JDeferred; overload;
    function reject(args: TEventHandler): JDeferred; overload;
    function rejectWith(context: variant; args: array of variant): JDeferred;
    function resolve(args: array of variant): JDeferred; overload;
    class function resolve(value: variant = nil): JPromise; overload;
    function resolveWith(context: variant; args: array of variant): JDeferred;
    function all(iterable: Array of Variant): JPromise;
    function race(iterable: Array of Variant): JPromise;
  end;
{ global external functions }
function Promise : JDeferred; external 'Promise' property;
function Error(message: variant): variant; external 'Error';
function document: variant; external "document" property;
function window : Variant; external 'window' property;
function &typeof(obj:variant): variant; overload; external "typeof";

The following function returns a result asynchronously, via a Promise:

function asyncFunction(): JPromise;
begin
Result := new JPromise(
  function (resolve: TCallback): variant
  begin
    w3_SetTimeout(procedure()
    begin
      var value := 42;
      resolve('Async Hello world: ' + IntToStr(value) );
    end, 16);
  end,

  function(reject: TCallback): variant
  begin
   // case rejected
  end);
end;

{* 
  then() always returns a Promise, which enables you to chain method calls:
  Furthermore, note how catch() handles the errors of the asynchronous function asyncFunction(). 
*}


asyncFunction()
  .then(procedure (value: variant)
  begin
    console.log(value); // => 'Async Hello world'
  end)

  .catch(procedure (error: variant)
  begin
    console.log(error);
  end);

Chaining Promises
The real key here is that then() is returning a new promise. Since promises capture the notion of asynchronicity in an object, we can chain them, map them, have them run in parallel or sequential, all kinds of useful things.

Code like the following is very common with promises:

asyncFunction()
.then(filterTheData)
.then(processTheData)
.then(displayTheData);

What value does the second promise resolve to? It receives the return value of the first promise.
In other words, it’s what was passed into the first call to then(). The return value of that first handler is used to resolve the second promise. Thus chaining is accomplished!

The asyncFunction is returning a promise, as evidenced by the call to then(), "then() always returns a promise" but the result of that first then must also be a promise, as we call then() again (and yet again!)
That’s exactly what happens, if we can convince then() to return a promise, things get more interesting.
Since then() always returns a new promise object, there will always be at least one promise object that gets created, resolved and then ignored.

Example:

function asyncFunction(): JPromise;
begin
Result := new JPromise(
  function (resolve: TCallback): variant
  begin
    w3_SetTimeout(procedure()
    begin
      var value := 42;
      resolve('getting_The_Data: ' + IntToStr(value) );
    end, 16);
  end,

  function(reject: TCallback): variant
  begin
   // case rejected
  end);
end;

asyncFunction()
  .then(function (value: variant): variant
  begin
    console.log('first result: '+ value); // => 'getting_The_Data: 42'
    exit('filter_The_Data');
  end)

  .then(function (value: variant): variant
  begin
    console.log('second result: '+ value); // => 'filter_The_Data'
    exit('process_The_Data');  // explicitly returning the string "process_The_Data"
  end)

  .then(function (value: variant): variant
  begin
    console.log('third result: '+ value); // => 'process_The_Data'
    exit('display_The_Data');
  end)

  .then(function (value: variant): variant
  begin
    console.log('forth result: '+ value); // => 'display_The_Data'
  end)

  .catch(procedure (error: variant)
  begin
    console.log(error);
  end);
  
(*  the output is:
 first result: getting_The_Data: 42
 second result: filter_The_Data
 third result: process_The_Data
 forth result: display_The_Data   
*)
What if in the above example, we wanted all the results in the end in one go.

Executing asynchronous functions in parallel


Promises always resolve to one value. If you need to pass more than one value along, you need to create a
multi-value in some fashion (an array, an object, concatinating strings, etc).
With chaining, we would need to manually build up the result ourself. We can create a function to return a promise object such as:

["getting_The_Data: 42","filter_The_Data","process_The_Data","display_The_Data"] 

Example:

function asyncFunction(): JPromise;
begin
Result := new JPromise(
  function (resolve: TCallback): variant
  begin
    w3_SetTimeout(procedure()
    begin
      var value := 42;
      resolve('getting_The_Data: ' + IntToStr(value) );
    end, 16);
  end,

  function(reject: TCallback): variant
  begin
   // case rejected
  end);
end;

var results: array of variant;

asyncFunction()
  .then(function (value: variant): array of variant
  begin
    results := [value];
    results.push('filter_The_Data');
    exit(results);
  end)

  .then(function (value: variant): array of variant
  begin
    results.push('process_The_Data');
    exit(results);
  end)

  .then(function (value: variant): array of variant
  begin
    results.push('display_The_Data');
    exit(results);
  end)

  .then(function (value: variant): variant
  begin
    console.log( JSON.stringify(variant(results)) );
   {* for var i := results.Low to results.High do
    console.log(results[i]); *}

   {*for var j in results do
     console.log(j);*}
  end)

  .catch(procedure (error: variant)
  begin
    console.log(error);
  end);

The Callback is Optional

The callback to then() is not strictly required. If you leave it off, the promise resolves to the same value as the
previous promise.
NOTE: If there is no callback in method then(), it simply resolves the promise and exits.  The value is still the value of the previous promise.

Example:

function asyncFunction(): JPromise;
begin
Result := new JPromise(
  function (resolve: TCallback): variant
  begin
    w3_SetTimeout(procedure()
    begin
      var value := 42;
      resolve('getting_The_Data: ' + IntToStr(value) );
    end, 16);
  end,

  function(reject: TCallback): variant
  begin
   // case rejected
  end);
end;

asyncFunction()
  .then()

  .then()

  .then()

  .then(function (value: variant): variant
  begin
    console.log('forth result: '+ value); // => 'forth result: getting_The_Data: 42'
  end)

  .catch(procedure (error: variant)
  begin
    console.log(error);
  end);

Returning JSON object Inside the Chain

What if one of the resolved values is a JSON? For example:

function doSomethingElse(value: variant): variant;
begin
  result := JSON.parse('{"name":"'+value+'", "id":123}');
end;

asyncFunction()
  .then(function (value: variant): variant
  begin
    console.log('first result: '+ value); // => 
    { doSomethingElse returns a promise }
    exit( doSomethingElse(value) );
  end)

  .then(function (finalResult: variant): variant
  begin
    console.log(finalResult); // => Object {name: "getting_The_Data: 42", id: 123}
  end)

  .catch(procedure (error: variant)
  begin
    console.log(error);
  end);

Rejecting Promises (error handling support)

When something goes wrong during the course of a promise, it needs to be rejected with a reason.
How does the caller know when this happens?
They can find out by passing in a second callback to then()
The promise will transition from pending to either resolved or rejected, never both.
In other words, only one of the above callbacks ever gets called.
Promises enable rejection by means of reject(), the evil twin of resolve().
Here is asyncFunction() with error handling support added


function asyncFunction(): JPromise;
begin
  result := JPromise.create(function(resolve: TCallback; reject: TCallback): variant
  begin
    var res := doSomethingElse();
    if(res.error = true) then
    begin
      reject(res.error);
    end else
      resolve(res.value);
    end);
end;

asyncFunction()
  .then(function (value: variant): variant
  begin
    console.log('Success! '+ value);
    //console.log(value.error);
  end,
  function(error: variant): variant
  begin
    console.log('Uh oh '+ error);
  end)

  .catch(procedure (error: variant)
  begin
    console.log(error);
  end);

When using promises, it’s very easy to omit the error callback.
But if you do, you’ll never get any indication something went wrong. At the very least, the final promise in your chain should have an error callback.

Unexpected Errors Should Also Lead to Rejection
So far our error handling only accounts for known errors. It’s possible an unhandled exception will happen,
completely ruining everything. It’s essential that the promise implementation catch these exceptions and reject
accordingly. It’s possible for a misunderstanding of promises to lead to completely swallowed errors! This trips people up a lot.

Example:

function asyncFunction(): JPromise;
begin
  result := JPromise.create(
  procedure(resolve: TCallback; reject: TCallback)
  begin
    var badJson := "<div>uh oh, this is not JSON at all!</div>";
    resolve(badJson);
  end);
end;

asyncFunction()
  .then(function (jsonData: variant): variant
  begin
    var obj := JSON.parse(jsonData);
    console.log(obj);
    exit(obj);
  end,
  function (error: variant): variant
  begin
    console.log("an error occured: "+ error);
  end);

What is going to happen here? Our callback inside then() is expecting some valid JSON.
So it naively tries to parse it, which leads to an exception. But we have an error callback, so we’re good, right?
Nope. That error callback will not be invoked! If you run this example, you will get no output at all. No errors, no nothing. Pure chilling silence.
Why is this? Since the unhandled exception took place in our callback to then(), it is being caught inside of handle().
This causes handle() to reject the promise that then() returned, not the promise we are already responding to, as that promise has already properly resolved.
Always remember, inside of then()'s callback, the promise you are responding to has already resolved.
The result of your callback will have no influence on this promise.

If you want to capture the above error, you need an error callback further downstream, for instance:

asyncFunction()
  .then(function (jsonData: variant): variant
  begin
    var obj := JSON.parse(jsonData);
    console.log(obj);
    exit(obj);
  end)

  .then(nil, function (error: variant): variant
  begin
    console.log("an error occured: "+ error);
  end)

  .catch(procedure (error: variant)
  begin
    console.log(error);
  end);

Now we will properly log the error. In my experience, a potentially better solution would be implement a catch method to capture errors.


asyncFunction()
  .then(function (jsonData: variant): variant
  begin
    var obj := JSON.parse(jsonData);
    console.log(obj);
  end)

  .catch(procedure (error: variant)
  begin
    console.log(error);
  end);

Loading Images on-the-fly

Now, let's create a more realistic example using promise in SMS.
Let's create a function that dynamically loads an image based on the image URI:

Remember that it is passed an anonymous function with two parameters:
a) resolve() method that you call at some point to set the state of the promise to fulfilled,
b) reject() method to set it to rejected instead.
A Promise object starts out with a state of pending, to indicate the asynchronous code it's monitoring has neither completed (fulfilled) or failed (rejected).

Example:

function getImage(url: variant): JPromise;
begin
Result := JPromise.create(
  procedure(resolve: TCallback; reject: TCallback)
  var img: JHTMLImageElement;
  begin
    img := JHTMLImageElement(Document.createElement('img'));
    JGlobalEventHandlers(img).onload := lambda
      resolve(url)
    end;
    JGlobalEventHandlers(img).onerror := lambda
      reject(url)
    end;
    img.src := url;
end);
end;

The getImage() function returns a Promise object that keeps track of the state of the image load.
Its promise object goes from the initial state of "pending" to either fulfilled or rejected eventually depending on the outcome of the image load.

Notice how we've passed the URI of the image to both the resolve() and reject() method of Promise;
this could be any data you wish to be processed further depending on the outcome of the task.
Ok, at this point Promises may just seem like a pointless exercise to set some object's state to indicate the status of a task. But as you'll soon see, with this mechanism comes the ability to easily and intuitively define what happens next once the task is completed.

The then() and catch() methods
Whenever you instantiate a Promise object, two methods:
a) then() method and
b) catch() method become available to decide what happens next after the conclusion of an asynchronous task.

Take a look at the below:
Here as soon as "test.png" has loaded, we specify that the image be shown inside the "OBJ3" DIV.
The original getImage() function returns a Promise object, so we can call then() on it to specify what happens when the request has been resolved. The URL of the image we passed into the resolve() function when we created getImage() becomes available as the parameter inside the then() function.

What happens if the image failed to load? The then() method can accept a 2nd function to deal with the rejected state of the Promise object:

Example:

getImage('test.png')
  .then(function (successurl: variant): variant
  begin
    document.getElementById('OBJ3').innerHTML := '<img src="' + successurl + '" />';
  end,
  function(errorurl: variant): variant
  begin
    console.log("error loading "+ errorurl);
  end);
In such a construct, if the image loads, the first function inside then() is run, if it fails, the 2nd instead.

Of course, we can also handle errors using the catch() method instead:
Example:

getImage('test.png')
  .then(function (successurl: variant): variant
  begin
    document.getElementById('OBJ3').innerHTML := '<img src="' + successurl + '" />';
  end)
  
  .catch(procedure (errorurl: variant)
  begin
    console.log("error loading "+ errorurl);
  end);  
  
  {*  Calling catch() is equivalent to calling then(undefined, function), 
so the above is the same as: *}
  
getImage('test.png')
  .then(function (successurl: variant): variant
  begin
    document.getElementById('OBJ3').innerHTML := '<img src="' + successurl + '" />';
  end)

  .then(nil, function (errorurl: variant): variant
  begin
    console.log('Error loading ' + errorurl)
  end);

Fetching and displaying images sequentially

Lets say we have an array of images we want to load and display sequentially.
That is to say, first load and show image1, and once that's complete, go on to image2, and so on.
We'll talk about chaining promises together further below to accomplish this, but one approach is just to use
recursion to go through the list of images, calling our getImage() function each time with a then() method that
shows the current image before calling getImage() again until all of the images have been processed.

Here is the code:
function getImage(url: variant): JPromise;
begin
Result := JPromise.create(
  procedure(resolve: TCallback; reject: TCallback)
  var img: JHTMLImageElement;
  begin
    img := JHTMLImageElement(document.createElement('img'));
    JGlobalEventHandlers(img).onload := lambda
      resolve(url)
    end;
    JGlobalEventHandlers(img).onerror := lambda
      reject(url)
    end;
    img.src := url;
end);
end;

var doggyplayground := document.getElementById('OBJ3');
var doggies : Array of variant = ['dog1.png', 'dog2.png', 'dog3.png', 'dog4.png', 'dog5.png'];

procedure displayimages(images: array of variant);
begin
    var targetimage := variant(images).shift(); // process doggies images one at a time
    if (targetimage) then begin // if not end of array

    getImage(targetimage)
        .then(function(url: variant): variant  // load image then...
        begin
        
          var dog := JHTMLImageElement(document.createElement('img'));
          dog.setAttribute('src', url);
          doggyplayground.appendChild(dog); // add image to DIV
          displayimages(images); // recursion- call displayimages() again to process next image/doggy
        end)

        .catch(function(url: variant): variant // handle an image not loading
        begin
          console.log('Error loading ' + url);
          displayimages(images); // recursion- call displayimages() again to process next image/doggy
        end);
    end;
end;

displayimages(doggies);

The displayimages() function takes an array of images and sequentially goes through each image, by calling
images.shift(). For each image, we first call getImage() to fetch the image, then the returned Promise object's then() method to specify what happens next, in this case, add the image to the OBJ3 DIV before calling displayimages() again.

In the case of an image failing to load, the catch() method handles those instances.
The recursion stops when the doggies array is empty, after Array.shift() has gone through all of its elements.
Using recursion with JavaScript Promises is one way to sequentially process a series of asynchronous tasks.
Another more versatile method is by learning the art of chaining promises.

Chaining Promises

We already know that the then() method can be invoked on a Promise instance to specify what happens after the completion of a task. However, we can in fact chain multiple then() methods together, in turn chaining multiple promises together, to specify what happens after each promise has been resolved, in sequence. Using our trusted getImage() function to illustrate, the following fetches one image before fetching another:

Example:

function getImage(url: variant): JPromise;
begin
Result := JPromise.create(
  procedure(resolve: TCallback; reject: TCallback)
  var img: JHTMLImageElement;
  begin
    img := JHTMLImageElement(Document.createElement('img'));
    JGlobalEventHandlers(img).onload := lambda
      resolve(url)
    end;
    JGlobalEventHandlers(img).onerror := lambda
      reject(url)
    end;
    img.src := url;
end);
end;

getImage('dog1.png')
  .then(function (successurl: variant): variant
  begin
    console.log(successurl+ ' fetched!');
    exit( getImage('dog2.png') );
  end)

  .then(function (url: variant): variant
  begin
    console.log(url+ ' fetched!');
  end)

  .catch(procedure (error: variant)
  begin
    console.log(error);
  end);

This fetches "dog2.png" and returns a Promise object. By returning a Promise object inside then(), the next then() waits for that promise to resolve before running, accepting as its parameter the data passed on by the new Promise object. This is the key to chaining multiple promises together- by returning another promise inside the then() method.

Note that we can also simply return a static value inside then(), which would simply be carried on and executed immediately by the next then() method as its parameter value.
With the above example we still want to account for an image not loading, so we'll include the catch() method as well:

Example:

getImage('baddog1.png')
  .then(function (successurl: variant): variant
  begin
    console.log(successurl+ ' fetched!');
  end)

  .catch(procedure (url: variant)
  begin
    console.log(url+ ' failed to load!');
  end)

  .then(function (url: variant): variant
  begin
    exit( getImage('dog2.png') );
  end)

  .then(function (url: variant): variant
  begin
    console.log(url+ ' fetched!');
  end)

  .catch(procedure (url: variant)
  begin
    console.log(url+ ' failed to load!');
  end);

{ OUTPUT
 baddog1.png failed to load!
 dog2.png fetched!
}

Recall that catch() is synonymous with then(undefined, functionref), so after catch() the next then() will still be executed. Notice the organization of the then() and catch() methods- we put the return of the next promise object (or link in the chain) inside its own then() method, after the outcome of the previous promise is completely accounted for via the then() and catch() method proceeding it.
If you wanted to load 3 images in succession, for example, we could just add another set of then() then() catch() to the above code.

Creating a sequence of Promises

Ok, so we know the basic idea of chaining promises together is to return another promise inside the then() method. But manually chaining promises together can quickly become unmanageable. For longer chains, what we need is a way to start with an empty Promise object and programmatically pile on the desired then() and catch() methods to form the final sequence of promises.

We can create a blank Promise object that's resolved to begin with with the line:

var resolvedPromise := JDeferred.resolve();

var doggies : Array of variant = ['dog1.png', 'dog2.png', 'dog3.png', 'dog4.png', 'dog5.png'];

variant(doggies).forEach(
  procedure(targetimage: variant)
  begin

    resolvedPromise
      .then(function(): variant
      begin
        exit( getImage(targetimage) );
      end)

      .then(function(url: variant): variant
      begin
        console.log(url + ' fetched!');
      end)

      .catch(function(err: variant): variant
      begin
        console.log(err + ' failed to load!');
      end);
  end);
  
{
Console log:
 dog1.png fetched
 dog2.png fetched!
 dog3.png fetched!
 dog4.png fetched!
 dog5.png fetched!
}

First we create a resolved Promise object called sequence, then go through each element inside the doggies[] array with forEach(), adding to sequence the required then() and catch() methods to handle each image after it's loaded. The result is a series of then() and catch() methods attached to sequence, creating the desired timeline of loading each image one at a time.

In case you're wondering, instead of using forEach() to cycle through the image array, you can also use a simple for loop instead, though the result may be more than you had bargained for:


var resolvedPromise := JDeferred.resolve();

var doggies : Array of variant = ['dog1.png', 'dog2.png', 'dog3.png', 'dog4.png', 'dog5.png'];

for var i:= 0 to doggies.length - 1 do
begin
  var closure := lambda
    var capturedindex := i;  // capture i at each step of loop

    resolvedPromise
      .then(function(): variant
      begin
        exit( getImage(doggies[capturedindex]) );
      end)

      .then(function(url: variant): variant
      begin
        console.log(url + ' fetched!');
      end)

      .catch(function(err: variant): variant
      begin
        console.log('Err loading '+ err);
      end);
  end;
  closure(); // invoke this function immediately
end;
{
Console log:
 dog1.png fetched
 dog2.png fetched!
 dog3.png fetched!
 dog4.png fetched!
 dog5.png fetched!
}

Inside the for loop, to properly get the value of i at each step and pass it into then(), we need to create an outer closure to capture each value of i. Without the outer closure, the value of i passed into then() each time will simply be the value of i when it's reached the end of the loop, or doggies.length - 1.

Creating an array of promises

Instead of chaining promises together, we can also create an array of promises. This makes it easy to do something after all of the asynchronous tasks have completed, instead of after each task.

For example, the following uses getImage() to fetch two images and store them as an array of promises:

var doggypromises : array of variant = [getImage('dog1.png'),
                                        getImage('dog2.png'),
                                        getImage('dog3.png'),
                                        getImage('dog4.png'),
                                        getImage('dog5.png')];

var resolvedPromise := JDeferred.all( doggypromises );

    resolvedPromise
      .then(function(urls: variant): variant
      begin
        console.log(urls); // logs ["dog1.png", "dog2.png", "dog3.png", "dog4.png", "dog5.png"]
      end)

      .catch(function(err: variant): variant
      begin
        console.log(err);
      end);

Promise.all() takes an iterable (array or array-like list) of promise objects, and waits until all of those promises have been fulfilled before moving on to any then() method attached to it. The then() method is passed an array of returned values from each promise.

So what happens if one of the promises inside the array doesn't resolve (is rejected)? In that case the entire then() portion is ignore, and catch() is executed instead. So in the above scenario, if one or more of the images fails to load, it only logs an array of images that failed to load inside catch().

Displaying images when they have all been fetched (Fetch and display images at all once):

It's high time now to see an example of showing off all the doggies when they have been fetched, instead of one at a time. We'll use Array.map() to ease the pain in creating a promise array:


var doggies : array of variant = ['dog1.png', 'dog2.png', 'dog3.png', 'dog4.png', 'dog5.png'];
var doggypromises := doggies.map(getImage); // call getImage on each array element and return array of promises
var doggyplayground := document.getElementById('OBJ3');

var resolvedPromise := JDeferred.all( doggypromises );

resolvedPromise
  .then(function(urls: variant): variant
  begin
    for var i:=0 to urls.length - 1 do
    begin
      var dog := document.createElement('img');
      dog.setAttribute('src', urls[i]);
      doggyplayground.appendChild(dog);
    end;
  end)

  .catch(function(err: variant): variant
  begin
    console.log(err);
  end);

Array.map() iterates through the original array and calls getImage() on each element, returning a new array using the return value of getImage() at each step, or a promise. The result is twofold- each image gets fetched, and in turn we get back an array of corresponding promises. Then, we put Promise.all() to work, passing in doggypromises to show all the images at once:

Fetch images all at once, but display then in sequence as each one becomes ready 
(fetch images all at once in parallel, but show them sequentially):

Finally, as if the dogs haven't been paraded enough, lets introduce them to the doggy park in an optimized manner, not one by one, not all at once, but the best of both words. We'll fetch all of the images at once to take advantage of parallel downloading in browsers, but show them in sequence as each one becomes available (fetched).

This minimizes the time the doggies show up while still showing them in orderly sequence.
To do this, we just have to do two things we already know- create an array of promises to fetch all images at once (in parallel), then create a sequence of promises to actually show each image one at a time:

var doggies : array of variant = ['dog1.png', 'dog2.png', 'dog3.png', 'dog4.png', 'dog5.png'];
var doggypromises := doggies.map(getImage); // call getImage on each array element and return array of promises
var doggyplayground := document.getElementById('OBJ3');

var resolvedPromise := JDeferred.resolve();

variant(doggypromises).forEach(
  procedure(curPromise: variant)
  begin

    resolvedPromise
      .then(function(): variant
      begin
        exit( curPromise );
      end)

      .then(function(url: variant): variant
      begin
        var dog := document.createElement('img');
        dog.setAttribute('src', url);
        doggyplayground.appendChild(dog);
      end)

      .catch(function(err: variant): variant
      begin
        console.log(err + ' failed to load!');
      end);
  end);

Note that to create our sequence of promises this time, we iterate through the array of promises generated by Array.map(), and not the images array directly. This allows us to create the chain of promises without having to call getImage() each time again, which was done when we decided to fetch all images at once using Array.map() already.

Here's an example I re-created recently using promises with SMS: