DéveloppeurWeb.Com
    DéveloppeurWeb.Com
    • Agile Zone
    • AI Zone
    • Cloud Zone
    • Database Zone
    • DevOps Zone
    • Integration Zone
    • Web Dev Zone
    DéveloppeurWeb.Com
    Home»Performance Zone»Évaluation de JS dans le navigateur pour un produit à faible code
    Performance Zone

    Évaluation de JS dans le navigateur pour un produit à faible code

    novembre 13, 2021
    Évaluation de JS dans le navigateur pour un produit à faible code
    Share
    Facebook Twitter Pinterest Reddit WhatsApp Email

    Je travaille chez Appsmith, une plate-forme open source low code permettant aux développeurs de créer des outils et des workflows internes.

    Chez Appsmith, nos utilisateurs développeurs définissent la logique métier en écrivant n’importe quel code JS entre {{ }} liaisons dynamiques presque n’importe où dans l’application. Ils peuvent l’utiliser lors de la création de requêtes SQL, d’API ou de déclenchement d’actions. Cette fonctionnalité vous permet de contrôler le comportement de votre application avec le moins de configuration possible. Sous le capot, la plate-forme évaluera tout ce code de manière optimisée pour s’assurer que l’application reste performante mais réactive.

    Exemple de liaison dynamique

    Prenons l’exemple de la liaison d’une réponse de requête à un widget de table.

    Tout commence par les supports de reliure {{ }}. Lorsque la plate-forme voit ces crochets et du code dedans, dans une configuration de widget ou d’action, elle marque le champ comme un champ dynamique afin que notre évaluateur puisse le récupérer plus tard.

    Dans notre exemple, relions usersQuery à usersTable:

    Liaison d'usersQuery à usersTable

    Puisque nous avons ajouté cette liaison dans notre tableData champ, nous allons marquer ce champ et le stocker dans notre configuration de widget :

    // usersTable config
    {
      "usersTable": {
            ...
            "tableData": "{{
                usersQuery.data
                    .map(row => ({
                        name: row.name,
                        email: row.email
                    }))
                }}",
            "dynaminBindingPathList": [
                {"key": "tableData"}
                ...
            ]
        }
    }
    

    En arrière-plan, notre auditeur d’évaluation surveille toujours de tels événements qui nécessiteraient une évaluation. Pour notre exemple, il s’agit d’un scénario qui a définitivement besoin d’une évaluation, il lance donc notre évaluateur.

    Nous transmettons notre liste actuelle de données d’application construites dans ce que nous appelons DataTree au fil de discussion de l’évaluateur et attendez patiemment d’avoir de ses nouvelles :

    // DataTree
    {
        "usersQuery": {
            "config": {...},
            "data": [...]
        },
        "usersTable": {
            "tableData": "{{
                usersQuery.data
                    .map(row => ({
                        name: row.name,
                        email: row.email
                    }))
                }}",
            "dynaminBindingPathList": [{"key": "tableData"}]
        }
    }
    

    Pour des raisons de performances, nous exécutons notre processus d’évaluation dans un thread d’arrière-plan séparé avec l’aide de travailleurs Web. Cela garantit que les cycles d’évaluation de plus de 16 ms ne raccrochent pas le thread principal, ce qui donne à l’application la bande passante pour toujours répondre aux événements utilisateur.

    À l’intérieur du fil, l’écouteur d’événement reçoit un appel de réveil et se met au travail.

    • Obtenir des différences: Tout d’abord, il calculera les différences de DataTree de la dernière fois. Cela garantira que nous ne traitons que les modifications et non l’ensemble de l’arbre.

      Dans notre exemple, nous verrions le usersTable.tableData a changé et usersTable.dynamicBindingPathList a une nouvelle entrée.

      Il prend chaque différence, filtre les modifications sans importance et traite le reste.

    • Obtenir l’ordre d’évaluation avec la carte des dépendances: Il maintient également un DependencyMap entre diverses propriétés d’entité. L’évaluateur remarquera si des liaisons ont changé et recréera l’ordre de tri en conséquence.

      Pour notre exemple, nous en déduirons que usersTable.tableData dépend maintenant de usersQuery.data. Cela signifie que la réponse à la requête doit toujours être évaluée avant de pouvoir évaluer les données de la table et que chaque fois que nous voyons un changement dans la réponse à la requête, nous devons également réévaluer les données de la table :

      // DependencyMap
      {
          ...
          "usersTable.tableData": ["usersQuery.data"]
      }
    
      // Evaluation order
      [
          "usersQuery.data",
          "usersTable.tableData"
      ]
    

    • Évaluer: Après avoir créé un ordre d’évaluation optimisé, nous évaluerons la mise à jour de l’arbre, dans cet ordre. L’évaluation se fait via un eval fonctionner avec l’ensemble DataTree agissant comme sa portée mondiale. C’est pourquoi nous pouvons référencer directement n’importe quel objet dans notre DataTree dans notre code.
      // Evaluator
    
      const code = `
        usersQuery.data.map(row => ({
          name: row.name,
          email: row.email
        }))
      `;
    
      const scriptToEvaluate = `
        function closedFunction () {
          const result = ${code};
          return result
        }
        closedFunction()
      `;
    
      const result = eval(scriptToEvaluate);
    

    • Valider et analyser : Nous voulons toujours nous assurer que les valeurs renvoyées après évaluation sont dans le bon type de données que le widget attend. Cela garantit que le widget obtient toujours des données prévisibles, même si votre code a renvoyé des erreurs. Ceci est également nécessaire pour toute fonction en aval dans l’ordre d’évaluation, si elle fait référence à ce champ, obtiendra toujours un type de données raisonnable avec lequel travailler.

    Et cela l’achève. À la fin de cela, nous aurons une évaluation complète DataTree que nous pouvons ensuite renvoyer au thread principal et commencer à écouter tout nouvel événement pour recommencer tout ce processus.

    // Evaluated DataTree
    {
        "usersQuery": {
            "data": [...] 
        }
        "usersTable": {
            "tableData": [...]
        }
    }
    

    Notre fil principal reçoit un événement indiquant que l’évaluation est terminée, avec la nouvelle évaluation DataTree qu’il stocke dans l’état de redux de l’application. À partir de là, les widgets récupèrent leurs données et les rendent.

    Post-achèvement des données de rendu des widgets

    Résumé de notre philosophie

    • Tirer contre pousser : Lors de la création d’un générateur d’applications low code pour des développeurs variés, nous avons réfléchi sérieusement à la façon dont le code écrit fonctionne avec le reste de la plate-forme. Nous voulions que la configuration soit facile à démarrer mais puissante quand elle devait l’être. Pour cette raison, nous avons opté pour une architecture basée sur Pull plutôt que sur Push.
      Cela signifie que dans la plupart des cas, vous n’aurez pas à penser à la manière dont les données parviendront à un champ. Vous écrivez du code qui tire tout du monde DataTree et le place dans le champ où vous l’écrivez. De cette façon, au moment où les données sous-jacentes changent, elles se propagent à tous les champs qui en dépendent et vous, en tant que développeur, n’avez pas à orchestrer les modifications de l’interface utilisateur.
    • Flux de données unidirectionnel : Étant donné que nous sommes construits sur React.js et Redux, nous adoptons fortement le modèle de flux de données à sens unique. Cela signifie que vous ne pouvez pas définir les données d’une table directement dans ce champ à partir d’une autre partie de l’application. Si vous devez mettre à jour la table, vous devrez déclencher l’exécution de la requête, ce qui entraînera ensuite un nouveau rendu de la table avec les nouvelles données. Cela rend le code que vous écrivez facile à raisonner et les bogues faciles à trouver. Il encapsule également la logique de chaque widget et action en soi pour une bonne séparation des préoccupations.
    Share. Facebook Twitter Pinterest LinkedIn WhatsApp Reddit Email
    Add A Comment

    Leave A Reply Cancel Reply

    Catégories

    • Politique de cookies
    • Politique de confidentialité
    • CONTACT
    • Politique du DMCA
    • CONDITIONS D’UTILISATION
    • Avertissement
    © 2023 DéveloppeurWeb.Com.

    Type above and press Enter to search. Press Esc to cancel.