web-dev-qa-db-fra.com

Traiter un flux continu de JSON

La page (aujourd'hui disparue) http://stream.Twitter.com/1/statuses/sample.json utilisée pour renvoyer un flux continu et sans fin de données JSON.

Je voudrais le traiter à l'aide de jQuery (ou JavaScript, mais de préférence jQuery) à l'intérieur de ma propre page Web pour pouvoir afficher des effets visuels basés sur le flux en direct de tweets.

Depuis que je sache, la fonction jQuery parseJSON n'exécutera la fonction de rappel qu'après que toutes les données auront été envoyées par le serveur, mais il s'agit en fait d'un flux continu de données. Comment puis-je traiter les données "en temps réel" tout en conservant la connexion en cours?

62
Gabriele Cirulli

Ce genre de chose est mieux fait en utilisant WebSockets maintenant, qui selon CanIUse.Com est disponible dans tous les principaux navigateurs sauf Opera Mini (voir ce lien pour plus de détails sur les anciens navigateurs ou tous les navigateurs, et cliquez sur l'onglet Ressources pour voir encore plus de liens). Pour un aperçu, les sockets Web sont prises en charge dans IE 10+, Firefox 11+ (38+ si dans un contexte WebWorker), Chrome 16+, Opera 12.1+, Safari 7+, Android 4.4+, Opera Mobile 12.1+.

Remarque: vous voudrez probablement en savoir plus sur Service Workers and Web Workers , bien que ceux-ci aient des cas d'utilisation différents et des capacités différentes.

Cela ressemble à ceci:

var connection = new WebSocket(
   'ws://html5rocks.websocket.org/echo',
   ['soap', 'xmpp']
);

La connexion immédiate de certains gestionnaires d'événements à la connexion vous permet de savoir quand la connexion est ouverte, quand vous avez reçu des messages entrants ou si une erreur s'est produite.

L'envoi de messages devient aussi simple que cela:

connection.send('your message');
connection.send(binaryData);

Voir Présentation de WebSockets: apporter des sockets sur le Web pour une explication complète sur la façon de procéder.

Développeurs ASP.Net: si pour une raison quelconque vous devez prendre en charge des navigateurs plus anciens et que vous ne voulez pas découvrir par vous-même comment gérer ceux qui ne prennent pas en charge les WebSockets, envisagez d'utiliser une bibliothèque telle que SignalR .

L'ancienne réponse d'API EventSource pour les navigateurs plus anciens

La plupart des navigateurs implémentent désormais l'API EventSource , ce qui rend la lecture longue très facile, tant que le flux peut être fourni avec le type de contenu text/event-stream. Les navigateurs plus anciens ou les développeurs qui, pour une raison quelconque, ne peuvent pas concevoir le flux pour avoir ce type de contenu peuvent utiliser un script d'aide pour faire la même chose.

Voici un exemple:

var jsonStream = new EventSource('https://example.com/yourstreamingservice')
jsonStream.onmessage = function (e) {
   var message = JSON.parse(e.data);
   // handle message
};

Il s'agit essentiellement d'une version à part entière de la chose exacte que je décris ci-dessous.

La réponse de diffusion de service encore plus ancienne pour les navigateurs vraiment anciens

Ce que vous voulez s'appelle un long scrutin. Vous aurez besoin d'une fonction de gestion personnalisée AJAX onreadystatechange. Au lieu d'attendre la fin du flux entier (car il ne le sera jamais), vous devrez examiner périodiquement le contenu. Notez que vous devrez faire un gros travail pour que cela fonctionne dans IE 9 et inférieur, en utilisant un iframe.

Grossièrement:

  • Répondez à chaque onreadystatechange événement et examinez le flux qui vous a été donné au personnage actuel pour voir s'il y a suffisamment de données pour consommer un ou plusieurs événements discrets. Vous devrez analyser le flux vous-même avec des fonctions de gestion de chaînes javascript. Une combinaison de split, indexOf, d'expressions régulières, de boucle, etc. peut être utilisée pour accomplir cette tâche.
  • S'il n'y a pas encore assez de contenu, quittez et attendez le prochain événement.
  • Je suis sûr que chaque fois que le gestionnaire onreadystatechange se déclenche, le responseText sera toutes les données reçues jusqu'à présent. Définissez une variable persistante qui conservera la position du premier caractère qui n'a pas encore été correctement traité.
  • Une fois qu'il y a suffisamment de contenu pour qu'un ou plusieurs événements discrets apparaissent dans le flux, retirez-les un par un et passez-les à votre analyseur JSON pour réellement rendre le texte en tant qu'objets. Utilisez-les normalement.

Consultez cet HTTP Streaming Gist pour une ressource, ou Streaming comme alternative à l'interrogation du serveur sur SoftwareAs. Si vous devez prendre en charge IE 9 ou une version antérieure, vous devrez utiliser la méthode iframe pour cela.

Voici une citation de le livre Ajax Design Patterns: Création de sites Web 2.0 avec des modèles de programmation et de convivialité :

En résumé, Service Streaming rend l'approche HTTP Streaming plus flexible, car vous pouvez diffuser du contenu arbitraire plutôt que des commandes Javascript et parce que vous pouvez contrôler le cycle de vie de la connexion. Cependant, il combine deux technologies qui ne sont pas cohérentes entre les navigateurs, avec des problèmes de portabilité prévisibles. Les expériences suggèrent que la technique de streaming de page fonctionne à la fois sur IE [9 et versions antérieures] et Firefox, mais le streaming de service ne fonctionne que sur Firefox, que XMLHTTPRequest ou IFrame soit utilisé. Dans le premier cas, IE [9 ans et plus] supprime la réponse jusqu'à son terme, avec l'IFrame, cela fonctionne si une solution de contournement est utilisée: Le IE [9 ans et plus] accepte un message du serveur après les 256 premiers octets donc la seule chose à faire est d'envoyer 256 octets fictifs avant d'envoyer les messages. Après cela, tous les messages arriveront comme prévu. Un streaming de service complet est donc également possible dans IE [9 ans et plus]!

Rappelez-vous que cela date de 2006, donc il est définitivement obsolète, mais si vous devez prendre en charge des navigateurs plus anciens, c'est toujours pertinent.

Problèmes de sécurité

AJAX normal ne peut pas être interdomaine, ce qui signifie (maintenant que je fais attention au fait que vous voulez diffuser à partir de Twitter) que vous ne pourrez pas faire ce que vous demandez. Cela peut être résolu avec JSONP, mais JSONP par nature ne peut pas être diffusé en service et n'est d'ailleurs pas proposé par Twitter de toute façon. Il existe également Partage de ressources d'origine croisée (CORS), mais Twitter ne va pas le configurer pour vous - c'est le genre de chose qu'ils ne feraient que pour les domaines qui leur sont affiliés. Et CORS nécessite un navigateur moderne.

Votre seule option est donc de créer un service proxy sur votre serveur web qui effectue pour vous les requêtes sur Twitter puis vous remet les données. Cela ne peut être fait qu'à partir du même domaine que celui à partir duquel la page principale a été servie. Cela vous permettrait également de créer une version qui fonctionnera pour IE en utilisant la technique iframe. Si vous ne vous souciez pas des anciennes versions de IE, vous pouvez implémenter CORS vous-même pour contourner la restriction de domaine, si vous connaissez le domaine qui fera les demandes.

Si vous avez le contrôle total du logiciel client (comme s'il s'agissait d'un intranet d'entreprise), il existe une autre option: l'hébergement du navigateur Web à l'intérieur du formulaire utilisateur d'une application compilée exécutée localement. Je n'ai fait cela qu'en utilisant C # mais j'imagine que c'est possible à partir d'autres langages. Lorsque vous utilisez le bon objet de navigateur, car il est hébergé dans une application C #, l'application C # peut contourner les restrictions de sécurité inter-domaines, en lisant et en écrivant tout le contenu de la page, quel que soit le domaine dont il provient. Je doute que votre situation soit celle-ci mais je voulais mettre l'option ici pour ceux qui pourraient l'apprécier.

78
ErikE

J'ai un projet open source qui permet cela sur les navigateurs modernes (et revient à un style jQuery sur les anciens). La syntaxe d'appel est similaire à jQuery.ajax:

http://oboejs.com

8
jimhigson

L'URL que vous avez spécifiée dans votre question envoie un flux de réponse JSON. En raison de restrictions de sécurité inter-domaines dans les navigateurs, vous ne pouvez pas y accéder en utilisant javascript. Vous devrez implémenter un script côté serveur bridge sur votre serveur que vous pourriez interroger à intervalles réguliers en utilisant AJAX requêtes ou héberger votre site sur Twitter.com. Le premier semble plus réalisable.

3
Darin Dimitrov