Open / load async

Hi
in the Function below i'm trying to wait until all data are loaded and event fired in Procedure PreparaOrd(...); that call wdTOrdAfterScroll and wdROrdAfterOpen too but i tested function CreaModOrdine return before all data and event are fired !!

all this code is correctly wrote ?

Thx

Function TDM0.CreaModOrdine(CodUtente:String):TJSPromise; // Ritorna il nr. ordine, -1 errore
Begin
Result:=TJSPromise.New(Procedure(ASuccess, AFailed: TJSPromiseResolver)
Var QryOrd:String;
ResData:TaStrings;

Procedure PreparaOrd(OrdPK1:Integer = 0);
Begin
  Try
    With wdTOrd Do Begin
      OrdPK2:=0;

      If OrdPK1 = 0 Then Begin  // Nuovo ordine
        //Close();
        //SetJsonData('{}');
        Open();

        Insert();
        FieldByName('Cod_CliFor').AsString:=CodUtente;
        FieldByName('Inizio_Ins').AsDateTime:=Now();

        // Raccolgo tutte le info del cliente (rawinvoke) e le metto nell'ordine

        Post();
        ApplyUpdates();

      End Else Begin // Result > 0 c'è un ordine già aprto
        //QueryString:=Format('$filter=(PK_1 eq %d)',[OrdPK1]);
        Close();
        QueryString:=Format('$filter=(PK_1 eq %d)&$expand=ORD_RISTO_R/PK_1',[OrdPK1]);
        Load();
      End;

    End;
  Finally
    //Calc_RiepOrdine();
  End;
End;
// ---------------------------------------------------------
procedure OnDataResponse(DataResponse: TXDataClientResponse);
Var OrdPK1:Integer;
  Procedure MsgDlgProc(AValue: TModalResult);
  Begin
    If AValue = mrYes Then Begin  // Apre l'ultimo ordine sospeso del cliente
      // 1) Carica i dati e in wdROrdAfterOpen Apre il riepilogo
      PreparaOrd(OrdPK1);

      ASuccess(orMOD);
    End;
    If AValue = mrNo Then Begin
      // 1) Elimina sul server l'ordine sospeso dall'archivio ...
      QryOrd:=Format('DELETE FROM Ord_Risto_T WHERE PK_1 = %d ', [OrdPK1]);
      wdcData.RawInvoke('IDataService.Call_ServiceWeb',['QRY_CMD',QryOrd,-1], Nil);
      // 2) ... ne apre un altro nuovo ...
      PreparaOrd(0);

      ASuccess(orNEW);
    End;
  End;
Begin
  OrdPK1:=0;
  // NB : il nome del campo di ritorno è casesensitive, deve essere maiuscolo
  ResData:=GetJsonValues(String(DataResponse.Result),['PK_1']);
  If Length(ResData) > 0 Then
    OrdPK1:=StrToInt(ResData[0]);

  // Se già esiste un ordine chiede se lo si vuole riaprire gestendo i casi nella sotto procedura MsgDlgProc,
  // se non esiste ne crea uno nuovo
  If OrdPK1 > 0 Then
    frmMain.WebMessageDlg.ShowDialog(
      'Vuoi riprendere l''ultimo ordine sospeso ?'+#13#10+'(NO crea un nuovo ordine)', mtConfirmation, [mbYes, mbNo], @MsgDlgProc)
  Else Begin
    PreparaOrd(0);

    ASuccess(orNEW);
  End;
End;

Begin // promise
// Cerca un ordine già aperto per l'utente loggato, altrim. lo inserisce nuovo
QryOrd:=Format(
'SELECT PK_1 FROM Ord_Risto_T '+
'WHERE Cod_CliFor = ''%s'' AND Coalesce(Inizio_Ins,'''') <> '''' AND Coalesce(Fine_Ins,'''') = '''' ',
[CodUtente]);

wdcData.RawInvoke('IDataService.Call_ServiceWeb',['QRY_SEL',QryOrd,-1], @OnDataResponse);

End); // promise
End;

(Sorry i can't delete first post and then i rewrite better my post)

Hi
in the Function below i'm trying to wait until all data are loaded and event fired in Procedure PreparaOrd(...); that call wdTOrdAfterScroll and wdROrdAfterOpen too but i tested function CreaModOrdine return before all data and event are fired !!

all this code is correctly wrote ?

Thx

Function TDM0.CreaModOrdine(CodUtente:String):TJSPromise; // Ritorna il nr. ordine, -1 errore
Begin
  Result:=TJSPromise.New(Procedure(ASuccess, AFailed: TJSPromiseResolver)
    Var QryOrd:String;
      ResData:TaStrings;

    Procedure PreparaOrd(OrdPK1:Integer = 0);
    Begin
      Try
        With wdTOrd Do Begin
          OrdPK2:=0;

          If OrdPK1 = 0 Then Begin  // Nuovo ordine
            //Close();
            //SetJsonData('{}');
            Open();

            Insert();
            FieldByName('Cod_CliFor').AsString:=CodUtente;
            FieldByName('Inizio_Ins').AsDateTime:=Now();

            // Raccolgo tutte le info del cliente (rawinvoke) e le metto nell'ordine

            Post();
            ApplyUpdates();

          End Else Begin // Result > 0 c'è un ordine già aprto
            //QueryString:=Format('$filter=(PK_1 eq %d)',[OrdPK1]);
            Close();
            QueryString:=Format('$filter=(PK_1 eq %d)&$expand=ORD_RISTO_R/PK_1',[OrdPK1]);
            Load();
          End;

        End;
      Finally
        //Calc_RiepOrdine();
      End;
    End;
    // ---------------------------------------------------------
    procedure OnDataResponse(DataResponse: TXDataClientResponse);
    Var OrdPK1:Integer;
      Procedure MsgDlgProc(AValue: TModalResult);
      Begin
        If AValue = mrYes Then Begin  // Apre l'ultimo ordine sospeso del cliente
          // 1) Carica i dati e in wdROrdAfterOpen Apre il riepilogo
          PreparaOrd(OrdPK1);

          ASuccess(orMOD);
        End;
        If AValue = mrNo Then Begin
          // 1) Elimina sul server l'ordine sospeso dall'archivio ...
          QryOrd:=Format('DELETE FROM Ord_Risto_T WHERE PK_1 = %d ', [OrdPK1]);
          wdcData.RawInvoke('IDataService.Call_ServiceWeb',['QRY_CMD',QryOrd,-1], Nil);
          // 2) ... ne apre un altro nuovo ...
          PreparaOrd(0);

          ASuccess(orNEW);
        End;
      End;
    Begin
      OrdPK1:=0;
      // NB : il nome del campo di ritorno è casesensitive, deve essere maiuscolo
      ResData:=GetJsonValues(String(DataResponse.Result),['PK_1']);
      If Length(ResData) > 0 Then
        OrdPK1:=StrToInt(ResData[0]);

      // Se già esiste un ordine chiede se lo si vuole riaprire gestendo i casi nella sotto procedura MsgDlgProc,
      // se non esiste ne crea uno nuovo
      If OrdPK1 > 0 Then
        frmMain.WebMessageDlg.ShowDialog(
          'Vuoi riprendere l''ultimo ordine sospeso ?'+#13#10+'(NO crea un nuovo ordine)', mtConfirmation, [mbYes, mbNo], @MsgDlgProc)
      Else Begin
        PreparaOrd(0);

        ASuccess(orNEW);
      End;
    End;

  Begin  // promise
    // Cerca un ordine già aperto per l'utente loggato, altrim. lo inserisce nuovo
    QryOrd:=Format(
      'SELECT PK_1 FROM Ord_Risto_T '+
      'WHERE Cod_CliFor = ''%s'' AND Coalesce(Inizio_Ins,'''') <> '''' AND Coalesce(Fine_Ins,'''') = '''' ',
      [CodUtente]);

    wdcData.RawInvoke('IDataService.Call_ServiceWeb',['QRY_SEL',QryOrd,-1], @OnDataResponse);
  End);  // promise
End;
// -----------------------------------------------------------------------------
procedure TDM0.wdOrdAfterApplyUpdates(Sender: TDataSet; Info: TResolveResults);
Var i:Smallint;
  ResolveInfo:TResolveInfo;
begin
  For I:=0 to Length(Info.Records)-1 Do Begin
    ResolveInfo:=Info.Records[I];
    //If ResolveInfo.Status = TUpdateStatus.usResolveFailed Then Begin
    If ResolveInfo.Error <> '' Then Begin
      frmMain.WebMessageDlg.ShowDialog(ResolveInfo.Error, mtError, [mbOk], Nil);
      Exit;  // al primo errore esce !
    End;
  End;
end;
// -----------------------------------------------------------------------------
procedure TDM0.wdTOrdNewRecord(DataSet: TDataSet);
begin
  DataSet.FieldByName('ORD_RISTO_R').Value:=TJSArray.New();
end;
// -----------------------------------------------------------------------------
procedure TDM0.wdTOrdAfterScroll(DataSet: TDataSet);
begin
  //frmMain.WebMessageDlg.ShowDialog(
  //        'aft scroll', mtConfirmation, [mbYes, mbNo], Nil);

  wdROrd.Close();
  wdROrd.SetJsonData(wdTOrdORD_RISTO_R.Value);
  // GetJsonValues(String(wdTOrdORD_RISTO_R.Value),[],wdROrd);
  wdROrd.Open();
end;
// -----------------------------------------------------------------------------
procedure TDM0.wdROrdAfterOpen(DataSet: TDataSet);
begin
  // rilevo l'ultimo progressivo rigo per event. inserimenti successivi
  If DataSet.RecordCount > 0 Then Begin
    DataSet.Last();
    OrdPK2:=DataSet.FieldByName('PK_2').AsInteger;
  End;

  // Calc_RiepOrdine();  // NON USARLO QUA DA PROBLEMI
end;
// -----------------------------------------------------------------------------
procedure TDM0.wdROrdNewRecord(DataSet: TDataSet);
begin
  TJSObject(wdROrd.CurrentData)['PK_1@xdata.ref']:=
    Format('ORD_RISTO_T(%d)', [TJSObject(wdTOrd.CurrentData)['PK_1']]);

  Inc(OrdPK2);
  Dataset.FieldByName('PK_2').AsInteger:=OrdPK2;
end;
// -----------------------------------------------------------------------------
procedure TDM0.wdROrdBeforePost(DataSet: TDataSet);
begin
  With Dataset Do Begin
    FieldByName('Tot_Importo').AsFloat:=
          FieldByName('Quantita').AsFloat * FieldByName('Prezzo').AsFloat;
    FieldByName('Tot_Rigo').AsFloat:=FieldByName('Tot_Importo').AsFloat;
  End;
end;

Your code is already rather complex for a simple support question, but the culprit seems to be here:

   PreparaOrd(0);
   ASuccess(orNEW);

PreparaOrd performs async operations (ApplyUpdates and Load), thus it returns before those operations are finished. The ASuccess is immediately called, so your promised is "finished", but the calls to ApplyUpdates and Load as still being processed.

Then i must use the afterOpen and afterApplyUpd events to manage this situation and then this is only way to serialize this operations ?

Yes.

Hello! Have you found another way to solve this? It's a little bit hard to handle "afterOpen" and "afterApplyUpd" every request :neutral_face:

Thanks!!

+1

We will consider adding such Async methods for next release. We are stuck to TDataset compatibility, though. We will see what can be done.

Ok thanks! Really that issue stops my projects.
Best regards!

1 Like