Re: Connexion asynchrone en javascript

Page principale

Répondre à ce message
Auteur: Patrice Karatchentzeff
Date:  
À: Edgar Bonet
CC: guilde
Sujet: Re: Connexion asynchrone en javascript
Merci Edgard.

Je livre deux fichiers minimaux qui reproduisent l'erreur. Le premier
est l'App.js de Native React et le second le fichier pivot de Dancer2
pour le serveur. J'ai laissé mon code et le tien, pour passer
facilement de l'un à l'autre.

Tu as besoin de native-react d'installé et de Dancer2 : les 2
s'installent « assez » facilement.

GMail m'autorisant pas (hmmm...) à joindre les fichiers, je les copie-colle :

% cat server.pm
package server;
use Dancer2;

set session => "Simple";
set serializer => 'JSON';

hook 'before' => sub {
    response_header 'Access-Control-Allow-Origin' => '*';
};


post '/connect' => sub {
  my $post = from_json( request->body );
  debug request->body;
  my $login    = params('body')->{login};
  my $password = params('body')->{password};
  debug "\t\t login : $login   password : $password";
  if ( ($login eq 'PK') && ($password eq 'PK') ) {
    # nothing possible to add after sending a request
    debug "\t\t Valid login and password : state connected\n";
    session user => $login;
    debug "\t\t", ({"ConnectionState" => "connected"});
    my %state = ( ConnectionState => "connected" );
    debug "\t\t", %state;
    #send_as JSON => ({"ConnectionState" => "connected"});
    send_as JSON => \%state;
  }
  else {
    debug "\t\t Invalid login and password : state unconnected\n";
    debug "\t\t", ({"ConnectionState" => "unconnected"});
    send_as JSON => ({"ConnectionState" => "unconnected"});
  };
};


true;

(le hook ne sert à rien, puisque je désactive le CORS dans l'envoi)
Il faut aussi ajouter dans le fichier de conf

% cat config.yml
logger: Console

engines:
  logger:
    Console:
      log_level: core


pour activer les debug, sinon remplacer par des print perl suffit.

Pour React Native :

% cat App.js
import React, { useState, useEffect } from 'react';
import {
View,
Text,
} from 'react-native';

const ipAddress     = "192.168.1.103";
const portAddress   ="5000";
const httpProtocol  = "http";
const uriBase       = httpProtocol + "://" + ipAddress + ":" + portAddress ;



function App() {

const jsonReader = { 'login':"PK", 'password':"PK" };
let string = JSON.stringify(jsonReader);

const [message, setMessage] = useState("disconnected");

  const submitConnectAsync2 = async () => {
    return fetch(
      uriBase + '/connect', {
    mode: 'no-cors', // beurk...
    method: 'POST',
    headers: {
          'Accept' : 'application/json',
          'Content-Type' : 'application/json',
    },
    body: JSON.stringify(jsonReader),
      })
      //.then(response => {
      //    response.json();
      //    console.log("Response:", response.json());
      //    console.log("Fin de l'envoi");
      //})
      .then(text => {
        console.log(`Received ${JSON.stringify(text)}`);
          console.log("Coucou1");
        let json = JSON.parse(text);
        //setMessage(json);
        console.log("Coucou2");
      })
      //.then(json => {
      //    setMessage("Connecté à la main");
      //    console.log("(1) connection state:", message);
      //    console.log("Fin de la réception");
      //})
      .catch(error => {
    console.log("Transaction error:", error);
    //console.log("body:", JSON.stringify(jsonReader));
    //console.log("response:", response.son());
    //console.log("json:", json);
      });
  };
  console.log("(2) connection state:", message);


  useEffect(() => {
    submitConnectAsync2();
  }, []);



 return (
   <View style={{flex:1,backgroundColor:"white"}}>
     <Text>
       {message}
     </Text>
   </View>
  );


}
export default App;

Je lance avec

% npx expo start -- -c (pour vider les caches à chaque fois)

Pas besoin d'expo pour tester en mode serveur. Appuyez sur w une fois lancé.

Pour Dancer2,

% ~/perl5/bin/plackup -r bin/app.psgi

Note : il faut adapter les IP bien sûr...

Merci

PK

Le mer. 7 juin 2023 à 14:27, Edgar Bonet <guilde@???> a écrit :
>
> Patrice a écrit :
> > Received {}
>
> Ça veut dire que `text` est un objet, ce qui n'est pas normal : on
> s'attendait à du texte.
>
> > "[object Response]" is not valid JSON
>
> JSON.parse() s'attendait à recevoir du texte en entrée. À la place de
> ça, il a reçu on objet, qui a été implicitement converti dans le texte
> "[object Response]". C'est donc un objet de type Response qu'il a reçu
> en entrée.
>
> Je ne comprends pas d'où vient le problème. Avec
>
>     .then(response => response.text())
>     .then(text => { ...})

>
> la deuxième lambda aurait dû recevoir le texte, et non l'objet
> réponse...
>
> J'ai essayé de reproduire ton problème, mais sans succès. Voici mon code
> serveur (c'est du Node.js) :
>
> -- server.js -----------------------------------------------------------
> const http = require("http"),
>       fs = require("fs"),
>       data = { foo: 42, bar: true };

>
> http.createServer((req, res) => {
>     switch (req.url) {
>     case "/":  // Static HTML page
>         res.statusCode = 200;
>         res.setHeader("Content-Type", "text/html");
>         fs.createReadStream("index.html").pipe(res);
>         break;
>     case "/connect":  // Dynamic JSON content
>         res.statusCode = 200;
>         res.setHeader("Content-Type", "application/json");
>         res.end(JSON.stringify(data));
>         break;
>     default:  // Error
>         res.statusCode = 404;
>         res.setHeader("Content-Type", "text/plain");
>         res.end("Not found\n");
>     }
> })
> .listen(3000, "127.0.0.1", () => {
>     console.log("Server listening on http://localhost:3000/");
> });
> -- Fin de server.js ----------------------------------------------------

>
> et voici la page Web :
>
> -- index.html ----------------------------------------------------------
> <!DOCTYPE html>
> <html>
> <head>
> <script>
>
> const submitConnectAsync2 = async () => {
>     return fetch("connect")
>     .then(response => response.json())
>     .then(json => {
>         console.log("Received:", json);
>     })
>     .catch(error => {
>         console.log("Error:", error);
>     });
> };

>
> window.onload = () => {
>     document.querySelector("button").onclick = submitConnectAsync2;
> };

>
> </script>
> </head>
> <body>
>
> <button>Test</button>
>
> </body>
> </html>
> -- Fin de index.html ---------------------------------------------------
>
> Quand je clique sur le bouton, la console Firefox me montre
>
>     Received: ▶ Object { foo: 42, bar: true }

>
> où l'objet est cliquable, donc bien reconnu comme un objet.
>
> Est-ce que tu pourrais essayer de créer un exemple minimal qui reproduit
> ton problème ?
>
> À+,
>
> Edgar.
>



-- 
      |\      _,,,---,,_           Patrice KARATCHENTZEFF
ZZZzz /,`.-'`'    -.  ;-;;,_   mailto:patrice.karatchentzeff@gmail.com
     |,4-  ) )-,_. ,\ (  `'-'
    '---''(_/--'  `-'\_)