Jump to content
Sign in to follow this  
lynkfs

ecma.promise

Recommended Posts

a simple promise in vanilla javascript looks something like this

var promise1 = new Promise(function(resolve, reject) {
  setTimeout(function() {
    resolve('foo');
  }, 300);
});

promise1.then(function(value) {
  console.log(value);
  // expected output: "foo"
});

console.log(promise1);
// expected output: [object Promise]

 

Using the Ecma.promise unit the next code snippet does compile, but fails on execution ("reference error, PromiseInit is not defined")

  var Pinit := new JPromiseInit;

  var p := JPromise.Create(PInit);

  p.then(function(x:variant):variant
    begin
      result := x;
    end);

Googling 'PromiseInit' or "_Promise" only gives a handful of vague (and dated) references

Nonplussed

Share this post


Link to post
Share on other sites

I read a bit about this. Your JS example works and as promises do work natively now in JS, I think that ECMA.Promise is outdated (or never worked in the first place).

It's a better idea for us to write a new class to the RTL to handle promises. Do you have any suggestions on what you'd look for in a class to make it easy to use?

Share this post


Link to post
Share on other sites

The unit ECMA.Promise is broken. I use this definition Using Promises in SMS

unit uPromises;

interface

uses W3C.Console, W3C.DOM, W3C.XMLHttpRequest;

type
  TVariantDynArray = array of Variant;
  JDeferred = class;
  TJPromiseCallback = procedure(Value: Variant);
  TJDeferredObject_fn = function(d: TJPromiseCallback): Variant;
  TJDeferredObject = procedure(resolve: TJPromiseCallback; reject: TJPromiseCallback);
  TJPromiseCallback_fn = function(Value: Variant): Variant;
  TJDeferredEventHandler = function(event: Variant): Variant;

  JPromise = class external 'Promise'
    constructor Create(fn: TJDeferredObject_fn { = nil}); overload;
    constructor Create(resolve: TJDeferredObject_fn; reject: TJDeferredObject_fn); overload;
    constructor Create(fn: TJDeferredObject); overload;
    function always(alwaysCallbacks: TVariantDynArray): JPromise;
    function done(doneCallbacks: TVariantDynArray): JPromise; overload;
    function done(doneCallbacks: Variant): JPromise; overload;
    function fail(failCallbacks: TVariantDynArray): JPromise;
    function progress(progressCallbacks: TVariantDynArray): JPromise;
    function state(): string;
    function &then(doneCallbacks: Variant; failCallbacks: Variant{ = undefined};
      progressCallbacks: Variant { = undefined}): JPromise; external 'then';
    function &then(onFulfilled: TJPromiseCallback_fn = nil): JPromise; overload;
      external 'then';
    function &then(onFulfilled: TJPromiseCallback_fn; onRejected:
      TJPromiseCallback_fn): JPromise; overload; external 'then';
    function &then(onFulfilled: TJPromiseCallback; onRejected:
      TJPromiseCallback): JPromise; overload; external 'then';
    function catch(rejecTJPromiseCallback: Variant = nil): JPromise; overload;
    function catch(rejecTJPromiseCallback: TJPromiseCallback_fn): JPromise; overload;
    class function promise(target: Variant): JPromise;
  end;

type
  JDeferred = class external 'Promise'(JPromise)
    function notify(args: TVariantDynArray): JDeferred;
    function notifyWith(context: Variant; args: TVariantDynArray): JDeferred;
    function reject(args: TVariantDynArray): JDeferred; overload;
    function reject(args: Variant): JDeferred; overload;
    function reject(args: TJDeferredEventHandler): JDeferred; overload;
    function rejectWith(context: Variant; args: TVariantDynArray): JDeferred;
    function resolve(args: TVariantDynArray): JDeferred; overload;
    function resolve(value: Variant = nil): JPromise; overload;
    function resolveWith(context: Variant; args: TVariantDynArray): JDeferred;
    function all(iterable: TVariantDynArray): JPromise; overload;
    function race(iterable: TVariantDynArray): JPromise;
  end;

  { global external functions }
  function Promise : JDeferred; external 'Promise' property;
  function queue: JPromise; external 'Promise.resolve()';
  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";

  function wait(ms: Integer): JPromise;
  function getURI(url: string): Variant;
  function getFile(url: string): variant;
  //function myRequire(url: string): Variant;

implementation

function wait(ms: Integer): JPromise;
  function setTimeout(ahandler : TJPromiseCallback; aTimeout : Integer): Integer; external 'window.setTimeout';
begin
  result := JPromise.Create(
    procedure (resolve, reject: TJPromiseCallback)
    begin
      setTimeout(resolve, ms);
    end);
end;

function getURI(url: string): Variant;
var
  request: JXMLHttpRequest;

  procedure p(resolve: TJPromiseCallback; reject: TJPromiseCallback);
  // Standard XHR to load an image
    procedure doOnLoad;
    begin
      // This is called even on 404 etc
      // so check the status
      if (request.status = 200) then
      begin
       // If successful, resolve the promise by passing back the request response
       resolve(request.response);
      end
      else
      begin
        // Otherwise reject with the status text
        // which will hopefully be a meaningful error
        reject(Error('File didn''t load successfully; error code: ' + request.statusText));
      end;
    end;

    procedure doOnError;
    begin
      // Also deal with the case when the entire request fails to begin with
      // This is probably a network error, so reject the promise with an appropriate message
      reject(Error('There was a network error.'));
    end;

  Begin
    request := JXMLHttpRequest.Create;
    request.open('GET', url);

    // When the request loads, check whether it was successful
    request.addEventListener('load', @doOnLoad);
    // Handle network errors
    request.addEventListener('abort', @doOnError);
    // Send the request
    request.send();
  End;

begin
// Create new promise with the Promise() constructor;
// This has as its argument a function
// with two parameters, resolve and reject
  Result := JPromise.Create(@p);
end;

function getFile(url: string): variant;
begin
// Create new promise with the Promise() constructor;
// This has as its argument a function
// with two parameters, resolve and reject
Result := JPromise.create(
  procedure(resolve: TJPromiseCallback; reject: TJPromiseCallback)
  // Standard XHR to load an image
  var request: JXMLHttpRequest;
  begin
  request := new JXMLHttpRequest();
  request.open('GET', url);

  // When the request loads, check whether it was successful
  request.onload := lambda
  begin
    // This is called even on 404 etc
    // so check the status
    if (request.status = 200) then
    begin
     // If successful, resolve the promise by passing back the request response
     resolve(request.response);
    end
    else
    begin
      // Otherwise reject with the status text
      // which will hopefully be a meaningful error
      reject(Error("File didn't load successfully; error code: " + request.statusText));
    end;
  end;
  end;
  // Handle network errors
  request.onerror := lambda
    // Also deal with the case when the entire request fails to begin with
    // This is probably a network error, so reject the promise with an appropriate message
    reject(Error('There was a network error.'));
  end;
  // Send the request
  request.send();
end);
end;


/*
function myRequire( url: string): Variant;
  function ev(win: Variant; arr: array of Variant): Variant; external 'eval.apply';
  var
    ajax: JXMLHttpRequest;

  function onReady(event: JEvent): Variant;
  var
    script: Variant;
  begin
    script := ajax.response; // ?? ajax.responseText;
    if (ajax.readyState = 4) then begin
      case( (ajax.status)) of
      200: begin
        //eval.apply( window, [script] );
        ev( window, [script] );
        console.log('script loaded: '+ url);
      end else
        console.log('ERROR: script not loaded: '+ url);
      end;
    end;
  end;

begin
  ajax := JXMLHttpRequest.Create;
  ajax.open( 'GET', url, false ); // <-- the 'false' makes it synchronous
  ajax.onreadystatechange := @onReady;
  ajax.send(null);
end;*/

end.

 

Share this post


Link to post
Share on other sites

Like this a lot. Both your first link and the examples in the unit above.

I've been fairly happy with 'pascalising' vanilla js promises till now, but this approach 'promises' something better.

 

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

×