[Pas2js] DataSet at the beginning

warleyalex warleyalex at yahoo.com.br
Sat Nov 10 19:01:00 CET 2018


I want to load a JSON file from my own server containing an array into a
javascript Object variable.
I would like to do it at the beginning of page load in a "synchronous" way
because data is needed during page load. But I think synchronous
XMLHttpRequest on the main thread is deprecated because of its detrimental
effects to the end user's experience. 

In the project source: after 500ms call p1;
I use window.setTimeout(@p1, 500); and worked as expected!

if i use just in async way
p1;  // the JSON file still is loading, we can not properly set the
variables at the beginning. Any ideas?

How to load the dataset at the beginning of the project in async
XMLHttpRequest? 

------// uCDS -----------
unit uCDS;

{$mode objfpc}

interface

uses
  Classes, SysUtils, Types, JS, Web, DB, JSONDataSet;

type
  TControl = TObject;

type
  { TWDataSource }
  TWDataSource = class(TDataSource)
  private
  { private declarations }
    FParent: TControl;
    FLeft: Integer;
    FTop: Integer;
  protected
  { protected declarations }
  public
  { public declarations }

  published
  { published declarations }
    property Parent: TControl read FParent write FParent;
    property Left: Integer read FLeft write FLeft;
    property Top: Integer read FTop write FTop;
  end;

  type
    TConnectErrorEvent = procedure(Sender: TObject; ErrorCode: Integer);

type
  TDataSet = class;

type
  { TConnection }
  TConnection = class(TComponent)
  private
  { private declarations }
    FReq: TJSXMLHttpRequest;
    FDS: TDataSet;
    FParent: TControl;
    FLeft: Integer;
    FTop: Integer;
    FActive: Boolean;
    FDataNode: String;
    FURI: String;
    FAfterConnect: TNotifyEvent;
    FBeforeConnect: TNotifyEvent;
    FOnConnectError: TConnectErrorEvent;
  protected
  { protected declarations }
    procedure SetActive(AValue: boolean);
  public
  { public declarations }
    function onLoad(Event: TEventListenerEvent): boolean;
    procedure RegisterDataSet(value: TDataSet);
    procedure DoBeforeConnect;
    procedure DoAfterConnect;
    procedure DoError(ErrorCode: Integer);
    constructor Create(AOwner: TComponent); override;
  published
  { published declarations }
    property Parent: TControl read FParent write FParent;
    property Left: Integer read FLeft write FLeft;
    property Top: Integer read FTop write FTop;
    property Active: Boolean read FActive write SetActive;
    property DataNode: String read FDataNode write FDataNode;
    property URI: String read FURI write FURI;
    property AfterConnect: TNotifyEvent read FAfterConnect write
FAfterConnect;
    property BeforeConnect: TNotifyEvent read FBeforeConnect write
FBeforeConnect;
    property OnConnectError: TConnectErrorEvent read FOnConnectError write
FOnConnectError;
  end;

type
  { TDataSet }
  TDataSet = class(TBaseJSONDataSet)
  private
  { private declarations }
    FConnection: TConnection;
    FParent: TControl;
    FLeft: Integer;
    FTop: Integer;
  protected
  { protected declarations }
    procedure SetConnection(Value: TConnection);
    Function CreateFieldMapper : TJSONFieldMapper; override;
  public
  { public declarations }
  published
  { published declarations }
    // Can be set directly if the dataset is closed. If metadata is set, it
must match the data.
    Property Rows;
    property Parent: TControl read FParent write FParent;
    property Left: Integer read FLeft write FLeft;
    property Top: Integer read FTop write FTop;
    property Connection: TConnection read FConnection write SetConnection;
  end;

implementation

{ TConnection }

procedure TConnection.SetActive(AValue: boolean);
begin
  if ((FURI <> '') and AValue) then
  begin
    DoBeforeConnect();
    FActive := AValue;
    FReq := TJSXMLHttpRequest.new;
    FReq.addEventListener('load', @onLoad);
    FReq.open('GET',FURI,true);
    FReq.send();
  end;
end;

function TConnection.onLoad(Event: TEventListenerEvent): boolean;
var
  J: JSValue;
 JA: JSValue;

begin
  if (FReq.status = 200) then
  begin
    J := TJSJSON.parse(FReq.responseText);
    JA := TJSObject(J).Properties[FDataNode];
    DoAfterConnect();
    if (assigned(FDS)) then
    begin
      FDS.Rows := TJSArray(JA);
      FDS.Open();
    end else
    DoError(FReq.status);
  end;
end;

procedure TConnection.RegisterDataSet(value: TDataSet);
begin
  FDS := value;
end;

procedure TConnection.DoBeforeConnect;
begin
  if (assigned(FBeforeConnect)) then
    FBeforeConnect(Self);
end;

procedure TConnection.DoAfterConnect;
begin
  if (assigned(FAfterConnect)) then
    FAfterConnect(Self);
end;

procedure TConnection.DoError(ErrorCode: Integer);
begin
  if (assigned(FOnConnectError)) then
    FOnConnectError(Self, ErrorCode);
end;

constructor TConnection.Create(AOwner: TComponent);
begin
  inherited; //Create(AOwner);
  FDS := nil;
end;

{ TDataSet }
procedure TDataSet.SetConnection(Value: TConnection);
begin
  if (assigned(Value)) then
    Value.RegisterDataSet(Self);
end;

Function TDataSet.CreateFieldMapper : TJSONFieldMapper;
begin
  Result := TJSONObjectFieldMapper.Create;
end;

end.
-------------------------

------// project1.lpr -----
program project1;

{$mode objfpc}

uses
  Classes, SysUtils, JS, Web, DB, JSONDataSet, uCDS;

var
  Connection1: TConnection;
  DataSet1: TDataSet;
  DataSource1: TWDataSource;

  procedure p1;
  begin
    while not DataSet1.EOF do
    begin
      console.log(
        DataSet1.FieldByName('Species_No').AsString,
        DataSet1.FieldByName('Category').AsString
      );
      DataSet1.Next;
    end;
  end;

begin
Connection1:=  TConnection.Create(nil);
Connection1.Name := 'Connection1';
Connection1.Active := false;

DataSet1:=     TDataSet.Create(nil);
DataSet1.Name := 'DataSet1';
DataSet1.Connection := Connection1;

DataSource1:=  TWDataSource.Create(nil);
DataSource1.Name := 'DataSource1';
DataSource1.DataSet := DataSet1;

Connection1.URI := 'data.json';
Connection1.DataNode := 'data';
DataSet1.FieldDefs.Clear();
DataSet1.FieldDefs.Add('Species_No', TFieldType.ftString,0);
DataSet1.FieldDefs.Add('Category',  TFieldType.ftString,50);
DataSet1.FieldDefs.Add('Common_Name', TFieldType.ftString,50);
DataSet1.FieldDefs.Add('Species_Name', TFieldType.ftString,50);
DataSet1.FieldDefs.Add('Length__cm_', TFieldType.ftInteger,0);
DataSet1.FieldDefs.Add('Length_In', TFieldType.ftString,30);
DataSet1.FieldDefs.Add('Notes', TFieldType.ftString,255);
Connection1.Active := true;

window.setTimeout(@p1, 500); 
//p1;

end.
-------------------------



--
Sent from: http://pas2js.38893.n8.nabble.com/


More information about the Pas2js mailing list