différence efficace réseau entre deux chaînes en Javascript
-
21-09-2019 - |
Question
J'ai une application web où un éditeur de côté client modifie un texte vraiment très grand qui est connu sur le côté serveur.
Le client peut faire toute sorte de modifications à ce texte.
Quel est le moyen le plus de transmettre la différence de résultat réseau efficace d'une manière que le serveur comprend? En outre, étant donné que cela se produira sur le côté client (Javascript), je voudrais aussi qu'il soit « rapide » (ou du moins pas sensiblement lente)
Certains scénarios:
- L'utilisateur modifie un caractère
- L'utilisateur modifie plusieurs phrases dans des positions aléatoires
- L'utilisateur efface tout et les résultats dans un texte vide.
Je ne peux pas utiliser la syntaxe diff-like car il est pas réseau efficent, il vérifie les lignes, où les exemples 1 et 3 produiront des différences horribles (en particulier la dernière un, où le résultat sera plus que l'ancien lui-même).
Toute personne a de l'expérience dans ce domaine? L'utilisateur fonctionne sur un ensemble très important de données - autour 3-5MB du texte, et de télécharger tout le contenu « nouveau » est un gros no-no
.Pour être clair, je suis à la recherche d'un « protocole » de transfert, comparaison de chaînes n'est pas la question.
La solution
Je ne suis pas très familier avec ce sujet, mais je peux vous pointer vers un projet open source (Apache License 2.0) qui peut être très utile.
Il est un Diff, Match et de la bibliothèque Patch écrit en plusieurs langues, y compris JavaScript, d'un ingénieur de Google et il est utilisé dans plusieurs services d'édition collaborative en ligne.
Voici une liste des ressources:
- Le projet Diff, Match et Patch
- Le projet MobWrite (mise en œuvre de l'éditeur basé sur le projet ci-dessus)
- "Synchronisation différentielle" (A Google Tech Talk par l'ingénieur)
Autres conseils
Une approche simple, en supposant que vous connaissez la copie sur le serveur ne va pas changer, serait juste d'envoyer une liste des modifications (suppressions et additions), avec les suppressions représentés comme un indice de début et de fin, et les additions représentés comme un index de départ et le texte à insérer.
Si vous avez plus qu'un simple algorithme de diff pour travailler avec (je ne sais pas exactement ce que vous entendez par « comparaison de chaînes n'est pas la question »), vous pouvez également détecter des morceaux déplacés ou copiés de texte, et les envoyer comme l'indice de début et de fin de la pièce déplacé ou copié du texte, ainsi que la destination pour l'insérer.
Notez que vous devez vous assurer de garder une trace de vos indices que se réfèrent au document original, ou le document édité jusqu'à présent. Une approche facile d'éviter ce problème est d'effectuer toujours les modifications de la fin du document vers le début; puis des modifications antérieures n'affecteront pas les compensations spécifiées par les modifications ultérieures.
Pour un exemple d'une approche comme celui-ci, voir le format ed
que diff -e
sorties . Ceci est essentiellement l'entrée qui pourrait être introduit dans l'éditeur de texte orienté ligne de ed
. Si vous voulez le plus petit diffs absolu d'envoyer à travers vous pouvez faire l'indexation de caractères à base plutôt que l'indexation en fonction de la ligne, mais la même approche de base pourrait fonctionner.
Toute modification peut être efficacement décomposé dans l'exécution de l'utilisateur: supprimer de X pour la longueur Y; insérer au texte X « whatever ». X et Y sont des décalages en caractères dès le début du texte; Y est un nombre de caractères; « Whatever » est une chaîne de caractères. Vous dites que vous avez besoin d'aucune aide calculer la diff, mais un exemple est
Vous pouvez envoyer uniquement les modifications, donc toutes les 500ms, quelle que soit modifications ont été apportées au cours des dernières 500ms serait envoyé, mais vous envoyer uniquement les données quand il y avait un changement. Dans ce que vous pouvez ensuite envoyer la position du mot a changé (s) et il suffit d'envoyer le mot entier, mais j'aurais la position soit à l'avant du texte. Il ne sera pas la peine plusieurs phrases, mais il peut y avoir plusieurs mots impliqués, mais, si vous les envoyez dans l'ordre de changement, le résultat doit être cohérent.
Parce qu'il ya tellement de façons de faire des modifications - même dans de courtes périodes comme 500ms - y compris glisser-déposer, ou couper et coller, de grandes sections de texte autour dans le document ou de l'extérieur - Je ne sais pas si ça va être quelque chose qui va couvrir tous les scénarios vraiment bien. Ceci est certainement une non-réponse à votre question à leur valeur nominale, mais je considère attentivement la peine de développer et de maintenir quelque chose comme ceci par rapport à l'évolution de l'interface pour limiter la taille du texte et de briser les textes existants en petits morceaux.
Peut-être que ce n'est pas possible dans votre situation, mais si elle est, je suppose que ce serait beaucoup moins de difficulté à la fin d'esquiver la question de cette façon et juste envoyer des documents complets après une édition.