web-dev-qa-db-fra.com

Comment écrire javascript côté client pour recevoir et analyser à temps la réponse `chunked '?

J'utilise le cadre de jeu pour générer une réponse fragmentée. Le code est:

class Test extends Controller {
    public static void chunk() throws InterruptedException {
        for (int i = 0; i < 10; i++) {
            String data = repeat("" + i, 1000);
            response.writeChunk(data);
            Thread.sleep(1000);
        }
    }
}

Lorsque j'utilise le navigateur pour visiter http://localhost:9000/test/chunk, Je peux voir les données affichées augmenter chaque seconde. Mais, lorsque j'écris une fonction javascript pour recevoir et gérer les données, j'ai constaté qu'elle se bloquerait jusqu'à ce que toutes les données soient reçues.

Le code est:

$(function(){
    $.ajax(
        "/test/chunked", 
        {
            "success": function(data, textStatus, xhr) {
                alert(textStatus);
            }
        }
    );
});

Je peux voir une boîte de message apparaître après 10 secondes, lorsque toutes les données reçues.

Comment obtenir le flux et gérer les données à temps?

37
Freewind

jQuery ne prend pas en charge cela, mais vous pouvez le faire avec du XHR ordinaire:

var xhr = new XMLHttpRequest()
xhr.open("GET", "/test/chunked", true)
xhr.onprogress = function () {
  console.log("PROGRESS:", xhr.responseText)
}
xhr.send()

Cela fonctionne dans tous les navigateurs modernes , y compris IE 10. Spécification W3C ici .

L'inconvénient ici est que xhr.responseText contient une réponse cumulée. Vous pouvez utiliser une sous-chaîne dessus, mais une meilleure idée est d'utiliser l'attribut responseType et d'utiliser slice sur un ArrayBuffer.

65
phil pirozhkov

Nous devrions bientôt pouvoir utiliser l'API ReadableStream ( documents MDN ici ). Le code ci-dessous semble fonctionner avec Chrome Version 62.0.3202.94:

fetch(url).then(function (response) {
    let reader = response.body.getReader();
    let decoder = new TextDecoder();
    return readData();
    function readData() {
        return reader.read().then(function ({value, done}) {
            let newData = decoder.decode(value, {stream: !done});
            console.log(newData);
            if (done) {
                console.log('Stream complete');
                return;
            }
            return readData();
        });
    }
});
4
rinat.io

l'événement success se déclencherait lorsque la transmission complète des données serait terminée et la connexion fermée avec un code de réponse 200. Je pense que vous devriez pouvoir implémenter un événement natif onreadystatechanged et voir les paquets de données au fur et à mesure.

0
kishu27