Jump to content

How make Server to wait until JSCode function return answer.


irigsoft

Recommended Posts

Hello.

How is possible to wait until javascript function on client side stop execution or return value in AjaxEvent

I use this on uniButton.OnClick

var

myMemo  TuniMemo

begin

   UniSession.AddJS  ('  var xhttp = new XMLHttpRequest();'
                    + '  xhttp.timeout = 2000;' // time in milliseconds
                    + '  xhttp.onreadystatechange = function() {'
                    + '    if (this.readyState == 4 && this.status == 200) {'
                    + '      var sRes = this.responseText;'
                    + '      ajaxRequest (' + myMemo.JSName
                    + '       , "FiscalAnswer", ["_value=" + sRes,"_cmd=" + "' + sCMD + '"])'
                    + '       ;'
                    + '    }'
                    + '  };'
                    + '  xhttp.open("GET", ''' + fURL + TRIM (UniMainModule.URLCommands.Text) + ''', true);'
                    + '  xhttp.send();'
                    );

end;

 

myMemo.OnAjaxEvent 

begin
TRY
 if EventName = 'FiscalCMD' then begin
    FiscalCMD := params.values['_cmd'];
end;

if EventName = 'FiscalAnswer' then begin
   FiscalCMD := params.values['_cmd'];
   TuniMemo(Sender).Text := params.values['_value'];
   UniMainModule.onError := (POS ('<Err Source=',params.values['_value']) > 0);
   If not DirectoryExists (ExtractFileDir(Application.ExeName) + '\Log\Tremol\') then
      ForceDirectories(ExtractFileDir(Application.ExeName) + '\Log\Tremol\');
   TuniMemo(Sender).Lines.SaveToFile(ExtractFileDir(Application.ExeName) + '\Log\Tremol\' + FiskalDevice.ID + '_' +  FormatDateTime('ddMMyyyy',Now,UniServerModule.MySettings) + '.log');
   //RetAnswer;

   If (UniMainModule.URLCommands.Count > 0)
   AND (not UniMainModule.onError)
   then begin
       UniMainModule.URLCommands.Delete (0);
   end;
   UniMainModule.onprint := False;
end;
EXCEPT
    on e:Exception do Dialogs.ShowMessage (EventName + ' - ' + e.message);
END;
end;

I want server to wait untill on ajaxevent ocure

Link to comment
Share on other sites

6 minutes ago, Sherzod said:

Well, I think so. Have you tried?

No.

But I get that my javascript function sometime have not return answer, just get respont = 200 .

So I catch this on ajax event.

 

mymemo.onAjaxEvent:

begin

TRY
 if EventName = 'FiscalCMD' then begin
    FiscalCMD := params.values['_cmd'];
end;

if (EventName = 'NoFiscalAnswer')
then begin
   FiscalCMD := params.values['_cmd'];
   TuniMemo(Sender).Text := 'ANSWER=' + params.values['_value'];
   uniMainModule.onprint := False;

   //go to the next command in list

If (UniMainModule.URLCommands.Count > 0)
   and (not UniMainModule.onError)
   then begin
      uniMainModule.SendtoFiscalDevice (TuniMemo(Sender),UniMainModule.URLCommands [0]);
   end;

end;


if EventName = 'FiscalAnswer' then begin
   TRY
   FiscalCMD := params.values['_cmd'];
   TuniMemo(Sender).Text := params.values['_value'];
   if TRIM (TuniMemo(Sender).Text) <> '' then begin
       UniMainModule.onError := (POS ('<Err Source=',params.values['_value']) > 0);
       If not DirectoryExists (ExtractFileDir(Application.ExeName) + '\Log\Tremol\') then
          ForceDirectories(ExtractFileDir(Application.ExeName) + '\Log\Tremol\');
       TuniMemo(Sender).Lines.SaveToFile(ExtractFileDir(Application.ExeName) + '\Log\Tremol\' + FiskalDevice.ID + '_' + FormatDateTime('ddMMyyyy',Now,UniServerModule.MySettings) + '.log');
   end;
   EXCEPT
        on e:Exception do Dialogs.ShowMessage (EventName + ' - ' + e.message);
   END;
   uniMainModule.onprint := False;

   //go to the next command in list

   If (UniMainModule.URLCommands.Count > 0)
   and (not UniMainModule.onError)
   then begin
          uniMainModule.SendtoFiscalDevice (TuniMemo(Sender),UniMainModule.URLCommands [0]);
   end;

end;
EXCEPT
    on e:Exception do Dialogs.ShowMessage (EventName + ' - ' + e.message);
END;

end;

 

my javascript function on button.Click

begin

   UniSession.AddJS  (//'function loadDoc() {' +
                   //old function use var xhttp = new XMLHttpRequest(); - end cause the problem

                  //, now i use let xhttp = new XMLHttpRequest(); - end all it's OK
                    '  let xhttp = new XMLHttpRequest();' 

                    + '  xhttp.timeout = 2000;' // time in milliseconds
                    + '  xhttp.onreadystatechange = function() {'
                    + '    if (this.readyState == 4 ) { '
                    + '         if (this.status == 200) {'
                    + '      var sRes = this.responseText;'
                    //+ '       alert ("HAVE responce");'
                    + '       ajaxRequest (' + myMemo.JSName
                    + '           , "FiscalAnswer", ["_value=" + sRes,"_cmd=" + "' + sCMD + '"]);'
                    + '         } else {'
                    //+ '               alert ("NO responce");'
                    + '               ajaxRequest (' + myMemo.JSName
                    + '                           , "NoFiscalAnswer", ["_value=" + "OK","_cmd=" + "' + sCMD + '"]);'
                    + '                };'
                    + '     };'
                    + '  };'
                    + '  xhttp.open("GET", ''' + fURL + TRIM (cmd) + ''', true);'
                    + '  xhttp.send();'
                    );

);

end;

Link to comment
Share on other sites

Hello,

@Sherzod 

I'm sorry, but I still have a problem getting information from the client.
The procedure works, but the server executes code and does not block.

So, I have this logic:

1. For a loop in a server

2. JSCode (Send url to device). I use Promises and XhttpRequest

3. in ajaxevent waiting for a response from the client

4. if the answer is true, go to the next one in the cycle from point 1.

This loop has a ShowMessage (intToStr (I)) for each step of the loop, but I get it once with the last value of the loop.

I even use ShowMask on ButtonClick.

Link to comment
Share on other sites

just function will post here.

uniMainModule - public UniMainModule.URLCommands : TStringList;

 

on btnclik to start loop:

procedure TUniForm_FiscalSettings.UniButton1Click(Sender: TObject);
var
sList : Integer;
begin
 

sList := 0;
FiskalDevice.ID := '';
FiskalDevice.MFP := '';
UniMainModule.onPrint := False;
UniMainModule.onError := False;

repeat
Inc (sList);
if UniCheckBox_CheckIfConnected.Checked then begin
   UniComboBox_FiscalID.ItemIndex := sList;
end;

//1 step - send settings to device

UniMainModule.URLCommands.Clear;
UniMainModule.URLCommands.Add ('/settings(com="' + UniComboBox_FiscalID.Text + '",tcp=0)');
UniMainModule.SendtoFiscalDevice_DirectAPI (uniMemo_Fisc,UniMainModule.URLCommands [0]);//procedure on client side

//2 step - if result from 1 step then get device ID

UniMainModule.URLCommands.Clear;
UniMainModule.URLCommands.Add ('/ReadSerialAndFiscalNums()');
UniMainModule.SendtoFiscalDevice_DirectAPI (uniMemo_Fisc,UniMainModule.URLCommands [0]);//procedure on client side

//send next command to device

UniMainModule.URLCommands.Clear;
UniMainModule.URLCommands.Add ('/PaperFeed()');
UniMainModule.SendtoFiscalDevice_DirectAPI (uniMemo_Fisc,UniMainModule.URLCommands [0]); //procedure on client side

//if have result from 2 step showmessage - just for test !

if FiskalDevice.ID > '' then begin
    ShowMessage ('Fisc ID: ' + FiskalDevice.ID);
    break;
end;

if FiskalDevice.ID <> '' then begin
end;

until (sList > UniComboBox_FiscalID.Count-1)
OR (FiskalDevice.ID <> '');

end;

Link to comment
Share on other sites

procedure on client side

declared in uniMainModule:

UniMainModule.SendtoFiscalDevice_DirectAPI (uniMemo_Fisc,UniMainModule.URLCommands [0]); //procedure on client side

var

sCMD, fURL   : string;

begin

If (TRIM (cmd) <> '')
//AND (not uniMainModule.onprint)
//OR (not uniMainModule.onError)
then begin
    TRY

    sCMD := StringReplace (COPY (cmd,2,POS ('(',cmd)-2),'"','',[rfReplaceAll]);
    fURL := UniServerModule.SistemSettingsList.Values ['PrintServer_URL'];
    UniMainModule.onprint := True;
    myMemo.Clear;
    //jQuery
//    UniSession.addJS ('$.get(''' + fURL + TRIM (cmd) + ''', function(responseText) {'
//                      + '       var sRes = responseText;'
//                      //+ '       alert ("HAVE responce:" + sRes);'
//                      + '       ajaxRequest (' + myMemo.JSName
//                      + '           , "FiscalAnswer", ["_value=" + sRes,"_cmd=" + "' + sCMD + '"]);'
//                      + '});'
//                      );

    //execute XMLHttpRequest
    UniSession.AddJS  ('  new Promise(function(resolve, reject) {' 
                    +  '  let xhttp = new XMLHttpRequest();'
                    + '  xhttp.timeout = 2000;' // time in milliseconds
                    + '  xhttp.onreadystatechange = function() {'
                    + '    if (this.readyState == 4 ) { '
                    + '         if (this.status == 200) {'

//must wait this to return onajaxevent

                    + '       var sRes = this.responseText;'
                    + '       ajaxRequest (' + myMemo.JSName
                    + '           , "FiscalAnswer", ["_value=" + sRes,"_cmd=" + "' + sCMD + '"]);'
                    + '         } else {'
                    + '               ajaxRequest (' + myMemo.JSName
                    + '                           , "NoFiscalAnswer", ["_value=" + "OK","_cmd=" + "' + sCMD + '"]);'
                    + '                };'
                    + '         resolve(this.responseText);'
                    + '     };'
                    + '  };'
                    + '  xhttp.open("GET", ''' + fURL + TRIM (cmd) + ''', false);'  //set to false to make server wait util client finish
                    + '  xhttp.send(null);'
                    + '});'//end Promise
                    );
    EXCEPT
          //on E: Exception do  Dialogs.ShowMessage ('SendtoFiscalDevice ERROR: ' + e.Message);//uniMainModule.onprint := False;
    END;
    If (UniMainModule.URLCommands.Count > 0)
    AND (not UniMainModule.onError)
    then begin
        UniMainModule.URLCommands.Delete (0);
        cmd := '';
    end;

end;

Link to comment
Share on other sites

on ajavaevent in myuniMemo on MainForm

if EventName = 'FiscalAnswer' then begin
   TRY
   FiscalCMD := params.values['_cmd'];
   TuniMemo(Sender).Text := 'ANSWER=' + params.values['_value'];
   if TRIM (TuniMemo(Sender).Text) <> '' then begin
       UniMainModule.onError := (POS ('<Err Source=',TuniMemo(Sender).Text) > 0);
       //if return error
       If (UniMainModule.onError) then begin
          UniMainModule.FiscalErrorTxt := TuniMemo(Sender).Text;
          //UniSession.AddJS('alert (' + params.values['_value'] + ')')
       end;
       RetAnswer;  //procedure work on aswer
       
       UniMainModule.onprint := False;
   end;
   EXCEPT
        //on e:Exception do Dialogs.ShowMessage (EventName + ' - ' + e.message);
   END;

   //go to execute next command in list

   If (UniMainModule.URLCommands.Count > 0)
   //and (not UniMainModule.onError)
   then begin
          uniMainModule.SendtoFiscalDevice_DirectAPI (TuniMemo(Sender),UniMainModule.URLCommands [0]);
   end;

end;
EXCEPT
    //on e:Exception do Dialogs.ShowMessage (EventName + ' - ' + e.message);
END;

Link to comment
Share on other sites

Here is the situation in real life:

1. uniGui StandAllone server

2. Android device (android WebView with uniGui application started on it) or on mobile browser 

3. Android third party server (application server to comunicate to device) instaled on Android device (same as pont 2)

4. UniGui Application send commands to point 3 with XHttpRequest

   url: http://localhost:4444/settings (com=deviceID,tcp=0); - no answer from point 3

  send next commmand: url http://localhost:4444/getDeviceinfo(); - must WAIT answer from point 3

when answer comming on ajaxevent, send next command http://localhost:4444/PaperFeed(); - must WAIT answer from point 3

 

Link to comment
Share on other sites

19 minutes ago, irigsoft said:

@Sherzod

I am sorry, is there a functionallity like Synchronize(Wait : boolean) and Synchronize(Delay : integer), but Synchronize(Wait : boolean)  - wait for some variable value?

I see on documentation that  Synchronize(Wait : boolean)  for user interaction.

Hello

Please check UniSweetAlert.Execute function.

You will understand how we are waiting for the result in the thread.

  • Upvote 1
Link to comment
Share on other sites

I did a few tests with the suggestions from here, but I think the example expects user interaction, maybe I'm wrong.

In my case I start a cycle from the server, which has 5 steps, on each a function is started by the user addJS, without interaction with the user (the Mask is visible) the server expects a response in the variable "print", and the response from the finished function I catch in "onajaxevent". I would like not to run step 2 of the cycle until I get the answer from step 1.

Now I'm experimenting with a combo box.
I start server procedure with onbuttonClick.

There are 5 values in it, for each of them I perform the function on the part of the user, which must return the third value in the list and the server to stop the cycle.
In this situation visually I get: The last value is loaded in the list and in one memo field I see how the results of the function are scrolled for all steps

 

for I := 0  to Combobox.Count - 1 do begin

Combobox.ItemIndex := I;

//start my clientside procedure  - uniMemo.onajaxevent

if ResultofClient = 3 then break;

end;

 

Solution UniMainModule.EnableSynchronousOperations must be true, to refresh combox on client Side.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...