Wie kann ich auf HTTP-Anfragen warten und dann eine Rückruffunktion auslösen?Ich habe die Sockets-Beispiele gelesen, aber ich kann JMP nur dazu bringen, den Empfang einer Anfrage zu bestätigen. Ich kann weder die Nutzdaten noch die Nachricht der Anfrage erhalten.Gibt es eine bessere Möglichkeit als Sockets oder Scheduler, um eine nicht blockierende Kommunikation zu erreichen?
Alles ist auf Windows.
Grundsätzlich ist mein Arbeitsablauf:
- Rendern Sie eine HTML-Seite mit JMP.
- Interagieren Sie mit den Daten mithilfe von Javascript, HTML und CSS
- Übergeben Sie das Ergebnis mithilfe einer Javascript-XMLHTTP-Anfrage an einen Python-Flask-Server
- Pingen Sie den Flask-Server kontinuierlich mit jmp über den Scheduler an, um zu sehen, ob auf dem Flask-Server Daten auf mich warten. Wenn dies der Fall ist, gibt Python die Daten zurück und JMP erhält sie als Antwort. Wenn nicht, erhält jmp die Zeichenfolge „ kein Update' und ich einfach zurückkehren .
- Aktualisieren Sie die JMP-Tabelle mit den Daten, die ich vom Server erhalten habe.
Ich möchte die Schritte 3 und 4 loswerden und Daten mithilfe dieser Javascript-xmlhttp-Anfrage mit einem nicht blockierenden Listener in jmp direkt VOM Browser zu JMP PUSHEN, der beim Empfang einer Anfrage einen Rückruf auslöst und die Daten in dieser Anfrage verwendet um meine Tabelle zu aktualisieren. Derzeit ist mein nicht blockierender „Listener“ eine Schleife, die den Scheduler spammt.
Dinge, die ich bisher gelesen habe:
Skriptindex: Sockets
Detaillierte Anleitung zur Verwendung von JSL zum Abrufen von Daten von der API
Socket-Kommunikation zum Abrufen und Protokollieren von Nachrichten von JMP-, R- und Python-Skripten
Ich verstehe das auch nicht: ((blobdata == Char To Blob( "" )) & (Left(r[2], 11) == "WOULDBLOCK:" ))
Was ist r[2]? Der Wert dieser Dinge wird immer wieder auf andere Dinge indiziert? In Python würde ich erwarten, etwas zu sagen wie:
R = Anfrage
my_dict.update({ 'last_jmp_data' :pd.DataFrame(request.json)})
Das funktioniert in Python, um meine Daten abzurufen, aber wenn ich versuche, sie an JMP zurückzugeben, werden nur die Header gedruckt. Ich kann nicht auf die von mir gesendeten JSON-Daten zugreifen. Ich gehe davon aus, dass meine Daten in einigen sind r[#] Element?
Ich versuche, etwas Nicht-Blockierendes zu schaffen, das Daten empfangen kann. Im Moment verwende ich eine hackige Lösung mit dem Scheduler, um den Workflow zu erstellen, und es funktioniert zwar, ist aber umständlich.
Ich verwende den Scheduler, um diese Funktion geplant zu halten. Dies trifft auf meinen Flask-Server, empfängt Daten als JSON zurück und aktualisiert meine Haupttabelle. Durch das Update löscht JMP alle Filter, sodass wir das in einer Zeichenfolge protokollieren und es dann erneut auf den Benutzer anwenden verliert nicht, was sie getan haben.
Ich möchte in der Lage sein, eine Anfrage über Javascript zu SENDEN und sie mit JMP abzurufen:
Das ist meine JavaScript-Funktion, ich brauche keine Antwort, ich möchte nur, dass sie zu JMP geht. Zuvor habe ich eine andere JavaScript-Problemumgehung verwendet, um eine JSON-Datei in meine Downloads zu schreiben, und meine Scheduler-Schleife verwendet, um den Download-Ordner des Benutzers auf eine bestimmte JSON-Datei zu überwachen, mit der die Tabelle aktualisiert werden soll.
Bei dieser Anwendung handelt es sich um eine Einzelbenutzer-App, die lokal auf dem PC des Benutzers ausgeführt wird und nicht mit externen Ressourcen kommuniziert. Ich musste lediglich meine GUI/bestimmte Dateninteraktionen in einem Browser durchführen, möchte diese Daten aber trotzdem wieder in JMP abrufen meine chimäre JMP/HTML/JS/CSS-Anwendung.
Javascript-Code, den ich verwende, um Daten vom Browser an meinen Python-Server zu senden. Ich möchte diesen direkt an JMP senden und mein Update durchführen, sobald es eintrifft.
var xhr = new XMLHttpRequest();
xhr.open("POST", 'http://localhost:8081', true);
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.send([my_json_data]);
Jmp-Schedulerschleife
//scheduled loop to ping python local server and see if it's time to update:
get_remote_update = Function({},
s = Schedule(.25,
//show("remote update fn");
//check_downloads_folder(); // old routine that was watching download folder
check_downloads_over_ip();
get_remote_update(); //loops by scheduling the event again
);JMP-Aufruf an den Python-Server, JSON-Daten empfangen und bei Bedarf aktualisieren.
//****************************************************************
//check_downloads_OVER_IP();
//****************************************************************
// EXPLORE THIS dt = Open( Char To Blob( request << Send() ), "JSON" );
// see if we can just get the response back into a table without creating it with the weird JMP thing
check_downloads_over_ip = Function({},
request = New HTTP Request(
URL("localhost:8088/get_update"),
Method("Post"),
Timeout( .5 ),
);
data=request << Send;
if((data != "No Update" > 0) & ( isempty(data) != 1 ),
obj = JSON:Parse( data );
dt = JSON:Make Table(obj);
dt << show window(0);
temp_dtf = CHAR(dtf <<GET script=""></GET>
Socket-Skripte Ich verstehe insbesondere diesen Teil nicht: //Alle empfangenen Daten in das Protokoll schreiben
Die Header werden im Protokoll gedruckt, aber ich kann nicht auf die von mir gesendeten JSON-Daten zugreifen.
Names default to here( 1 );
//Table to hold received data
dtLog = New Table( "Log",
New Column( "Time", Numeric, "Continuous", Format( "m/d/y h:m:s", 23, 0 ),
Input Format( "m/d/y h:m:s", 0 ) ),
New Column( "Client", Character, "Nominal" ),
New Column( "Message", Character, "Nominal" )
);
//Wait for and get data from remote machine
receivedata = Function( {c, waittime = 1, waitcount = 10},
//Varaible to store data received from remote machine
blobdata = Char To Blob( "" );
//Make socket is connected
r = c << GetPeerName();
//While receiving data or waiting to receive data
i = 0;
While(
(
(r[2] == "ok") |
((blobdata == Char To Blob( "" )) & (Left(r[2], 11) == "WOULDBLOCK:" ))
) &
(i < waitcount),
i++;
//Get data
r = c << recv( 100000 );
//If no data is received yet, wait
If(Left(r[2], 11) == "WOULDBLOCK:", Wait( waittime ) );
//Write whatever is received to the log
show("writing to log now");
Write( Blob to Char( r[3] ) );
show("Done writing to log now");
//join data to whatever is already received
blobdata = blobdata || r[3];
);
return( blobdata );
);
//Get log info from remote machine, store it in a data table
processlogconnection = function( {c},
//New row in log table
dtLog << Add Rows( 1 );
rowout = N Rows( dtLog );
Column( dtLog, "Time" )[rowout] = Today();
//Get computer name of remote machine
r = c << GetPeerName();
Column( dtLog, "Client" )[rowout] = r[3];
//Get message from the remote machine
Column( dtLog, "Message" )[rowout] = Blob to Char( receivedata( c ) );
//Close the connection
c << Close;
);
//Function to accept conections from remote machine, calls another
//function to handle communication with that machine
callbackfn = function( {x},
//Call another function with the connection returned from the Accept message
If( x[2] == "ok", processlogconnection( x[4] ) );
);
//Create a socket
con = Socket();
//Use a specific port on this computer
con << Bind( "localhost", "8081" );
//Tell this socket to be ready for other sockets to connect to it
Write( "\!nlistening on ", (con << getSockName)[3]);
con << Listen();
//Verify that the connection is active
con << getsockname;
//When something connects to this socket, call a function to handle
//the connection. Accept connections for the next 5 minutes.
con << Accept(callbackfn, 30000);
//Now messages can be sent to this connection.
//When all done, close the connection
//con << close();
Automatisierung und SkripterstellungErgebnisse teilen und kommunizierenWindowsBetreff: Wie kann ich auf HTTP-Anfragen warten und dann eine Rückruffunktion auslösen?Sie können die HTTP-Anfrage von JMP verwenden, um den Flask-Server anzupingen. Das würde einen Teil der Komplexität dessen beseitigen, was Sie tun möchten.
Sie können den Server mit HTTP-Anfragen abfragen (ich gehe von einer GET-Operation aus) und die Antwort direkt mit der Rückgabe lesen (wie eine JSON-Nutzlast) und dann, wenn sie fertig ist, HTTP-Anfrage erneut verwenden (wahrscheinlich als GET) und die Daten von verarbeiten der Kellner. Wenn Sie Sockets anstelle von HTTP/HTTPS verwenden, sollten Sie natürlich bei Ihrem Socket-Ansatz bleiben.
Betreff: Wie kann ich auf HTTP-Anfragen warten und dann eine Rückruffunktion auslösen?Außerdem unterstützen die Sockets von JMP kein https, sondern nur http. Sie sind ziemlich dünne Wrapper um Low-Level-Socket-Code und wissen nichts über das http-Protokoll: Sie müssen alles selbst erstellen. Ein vollständiges Beispiel finden Sie im Skriptindex:
The "listen" example is self-contained.The "listen" example is self-contained.The "listen" example is self-contained.The "listen" example is self-contained.The "listen" example is self-contained.The "listen" example is self-contained.The "listen" example is self-contained.The "listen" example is self-contained.The "listen" example is self-contained.The "listen" example is self-contained.The "listen" example is self-contained.The "listen" example is self-contained.The "listen" example is self-contained.The "listen" example is self-contained.The "listen" example is self-contained.The "listen" example is self-contained.The "listen" example is self-contained.The "listen" example is self-contained.The "listen" example is self-contained.The "listen" example is self-contained.The "listen" example is self-contained.The "listen" example is self-contained.The "listen" example is self-contained.The "listen" example is self-contained.The "listen" example is self-contained.The "listen" example is self-contained.The "listen" example is self-contained.The "listen" example is self-contained.The "listen" example is self-contained.The "listen" example is self-contained.The "listen" example is self-contained.The "listen" example is self-contained.The "listen" example is self-contained.The "listen" example is self-contained.The "listen" example is self-contained.The "listen" example is self-contained.The "listen" example is self-contained.The "listen" example is self-contained.The "listen" example is self-contained.The "listen" example is self-contained.The "listen" example is self-contained.The "listen" example is self-contained.The "listen" example is self-contained.The "listen" example is self-contained.The "listen" example is self-contained.The "listen" example is self-contained.The "listen" example is self-contained.The "listen" example is self-contained.The "listen" example is self-contained.The "listen" example is self-contained.The "listen" example is self-contained.The "listen" example is self-contained.The "listen" example is self-contained.Das „Listen“-Beispiel ist in sich geschlossen.
Es ist ziemlich schwierig, einen Webserver in JSL zu erstellen. Wenn Sie Python bereits von JMP verwenden, werfen Sie einen Blick auf Projektdatei für Jelly Video insbesondere der NumberServer. Ich musste mehrere Kopien von JMP ausführen, um die Bilder im Video zu produzieren, und ich brauchte eine Möglichkeit, ihnen die Arbeit zu übergeben, die sie erledigen mussten. Der Zahlenserver hat das erledigt und die Instrumentierung für ein JSL-Dashboard bereitgestellt, damit ich erkennen konnte, wann etwas Aufmerksamkeit erforderte. (Dieser Python-Server war meiner Meinung nach Single-Threaded, was sich als gute Sache für die Bereitstellung eindeutiger Nummern für gleichzeitige Anfragen erwies. Zumindest ist mir nie ein Duplikat aufgefallen...)
Betreff: Wie kann ich auf HTTP-Anfragen warten und dann eine Rückruffunktion auslösen?Beim erneuten Lesen stimme ich Bryan zu: Sie sollten eine HTTP-Anfrage verwenden, um mit dem Flask-Server zu kommunizieren.
Anscheinend sind Flask und Websockets auch gute Freunde: https://blog.miguelgrinberg.com/post/add-a-websocket-route-to-your-flask-2-x-application
Sehen WebSocket zum Beispiel; Ein Websocket ist eine bidirektionale Verbindung, die einfach für immer offen bleibt und eingehende Tröpfchen empfängt. Dadurch akzeptiert ein Browser Pushs von einem Server ohne Abfrage. Dieser Beispielcode verwendet den Python-Websocket und das RunProgram von JMP, um Blockierungsprobleme zu vermeiden.
Betreff: Wie kann ich auf HTTP-Anfragen warten und dann eine Rückruffunktion auslösen?Das klingt vielversprechend, dass Javascript auch WebSockets nativ erstellen kann.
Kann ein Laufprogramm Daten auf nicht blockierende Weise in JMP übertragen? Ich dachte, während Sie das externe Programm laufen lassen, wäre Ihre JMP-GUI blockiert?
Von dieser Seite:
Note: If you use Run Program() to launch a GUI program, JMP is inoperable until you close the program
Bearbeiten: Ich habe das tatsächlich schon heruntergeladen und einmal versucht, es zu verstehen! Ich werde es noch einmal versuchen.
Betreff: Wie kann ich auf HTTP-Anfragen warten und dann eine Rückruffunktion auslösen?Aber ist das nicht das, was ich gerade mache?
Ich interessiere mich nur für Sockets, weil es eine Möglichkeit zu sein scheint, einen nicht blockierenden Listener zu erstellen, im Gegensatz zu meinem aktuellen Mechanismus, HTTP-GET-Anfragen alle halbe Sekunde von JMP an Flask zu streamen, um zu sehen, ob sich der Webbrowser-Inhalt durch Benutzerinteraktion geändert hat. Ich hoffe, ein Ereignis von Flask oder Javascript an JMP zu übertragen, ohne dass JMP selbst etwas anfordert.
check_downloads_over_ip() Funktion //http get
UND get_remote_update(). // Scheduler-Schleife
get_remote_update() hält die check_downloads-Funktion ständig im Scheduler geplant, um sie „in Echtzeit“ zu machen.
Das Problem besteht darin, dass der Scheduler keine sehr elegante Möglichkeit bietet, nicht blockierendes Verhalten zu erzeugen.
Ich möchte, dass JMP zuhört (nicht blockierend) und dann kann ich eine HTTP-Anfrage von Javascript direkt im Browser an JMP senden und den Flask-Server vollständig eliminieren.
Der Knackpunkt ist, dass JMP über die Tools verfügt, um Daten von einem Server abzurufen und dann mit der Antwort zu arbeiten. Aber kann ich ein Ereignis vom Browser oder Server in JMP PUSH, ohne dass JMp zuerst etwas anfordert?
Ich werde die gesamte IP aus meiner App entfernen und ein Video veröffentlichen, um klarer zu machen, was ich vorhabe.
Betreff: Wie kann ich auf HTTP-Anfragen warten und dann eine Rückruffunktion auslösen?RunProgram kann N externe Programme gleichzeitig und asynchron ausführen. Wenn JMP ansonsten inaktiv ist, können die N RunPrograms ihre ReadFunction()-Skripte ausführen, während sie Daten auf stdin empfangen, und sie können Daten über stdout schreiben. Wenn Python das Programm ist, das RunProgram ausführt, ist Pythons stdin der stdout von RunProgram und ...stdout...stdin. (N kann wahrscheinlich nicht größer als ein paar Zehner sein.)
RunProgram kann Dinge wie Excel ausführen, aber das wird blockieren. RunProgram eignet sich viel besser für Befehlszeilenprogramme mit stdin und stdout. Sie könnten cmd.exe verwenden, oder Sie könnten verwenden plink um eine Shell auf einem Remote-Linux-Rechner zu öffnen. Oder Sie führen ein eigenes C- oder Python-Programm oder ein anderes Sprachprogramm aus.
RunProgram hat zwei Betriebsmodi: Wenn es ReadFunction("text") hat, läuft es im Blockierungsmodus, sammelt alle Standardausgaben und gibt eine Zeichenfolge zurück. Andernfalls wird es im nicht blockierenden Modus ausgeführt und gibt ein RunProgram-Objekt zurück die du bewahren musst in einer Variablen (andernfalls wird sie gelöscht, bevor der Prozess abgeschlossen ist.)
Es gibt nur wenige Befehle, die Sie an ein RunProgram-Objekt senden können. Sie können die Verbindung erfragen und Daten senden und empfangen.
Normalerweise verwende ich den Scheduler für solche Dinge nicht, weil er ein geöffnetes Fenster haben möchte, aber sehen Sie Neuigkeiten . Im selben Artikel wird gezeigt, wie Sie den CMD-Startbefehl verwenden, um den Msedge-Browser ohne Blockierungsverhalten auszuführen.
Ich habe Server in JSL geschrieben (gleicher Artikel), aber ich denke, dass es viel besser ist, eine Python- oder Python+Flask-Lösung zu verwenden. Wenn Sie flask verwenden, versuchen Sie Folgendes: Lassen Sie RunProgram den Python+flask-Code starten und geben Sie RunProgram etwas Logik in seiner Lesefunktion und Schreibfunktion, um mit dem Python-Code (stdin/stdout) zu kommunizieren. Fügen Sie im Python-Code einen Thread zur Kommunikation mit JMP hinzu. Der Flask-Server verfügt über einen eigenen Thread zur Bearbeitung von HTTP-Anfragen. Wenn der Server etwas an JMP senden muss, muss er dem JMP-Thread ein Ereignis signalisieren, das etwas an JMP druckt. Möglicherweise möchten Sie einen weiteren Python-Thread, der ein Leser-Thread ist und auf JMP wartet.
Betreff: Wie kann ich auf HTTP-Anfragen warten und dann eine Rückruffunktion auslösen?Danke! Ich werde diesen Ansatz ausprobieren.