web-dev-qa-db-ja.com

JavaScriptのフェッチから応答本文を再読み取りします

fetch()は、(成功した場合) Response オブジェクトに解決されるpromiseを返します。非常に一般的なことは、すぐに Response.json() を呼び出して、応答本文をJSONオブジェクトに変換することです。

応答本文が有効なJSONでない場合、Response.json() promiseはエラーで失敗します。メッセージは次の行に沿ったものです。

位置0のJSONの予期しないトークンX

問題を診断しようとするとき、それはあまり役に立ちません。理想的には、サーバーのコンテンツを表示できるようにしたい(これは多くの場合エラーメッセージです)。

ただし、ストリームは_Response.body_で1回しか読み取れないようです(少なくともChromeでは)。 (読み取り専用の _Response.bodyUsed_ フラグもあります。)Response.json()が本文をJSONに変換しようとしたときに既に発生しているため、本文は永久に失われているように見えますJSONの解析に失敗した場合。

元のfetch Promiseが解決したときに、元の応答本文を手動で読み取る(そしてJSONに変換する)以外に、元の応答本文を復元する方法はありますか?

15
Craig Walker

Response.clone() を使用して、Responseを複製します。

_let clone = response.clone();
_

または、ReadableStreamを返すResponse.body.getReader()を使用してResponseをストリームとして読み取り、TextDecoder()を使用して_Uint8Array_データストリームをテキストに変換します。

25
guest271314

JSON応答を時々失敗させるAPIを処理する必要がありました-response.json()を返す前に、応答オブジェクトのクローンを作成しました。 catchブロックを使用して、エラーがSyntaxErrorかどうかを判断し、応答クローンのテキスト結果を使用してエラーの修正に進むことができます

このような少し:

var brokenJson = function (url) {
    var responseCopy;
    return fetch(url)
    .then(function (response) {
        responseCopy = response.clone();
        return response.json();
    }).catch(function (err) {
        if (err instanceof SyntaxError) {
            return responseCopy.text()
            .then(function(data) {
                return fixJson(data);
            });
        }
        else {
            throw err;
        }
    }).then(function (json) {
        // do things
    });
};

fixJsonは、受信したデータを修正する関数です-私の場合、JSONが壊れていた場合、常に同じように壊れていました-余分な先頭{または末尾}があったと思います-思い出せません

質問を読み直すと、jsonを修正するのではなく、コンソールにエラーを記録する可能性が高くなります-簡単な書き換え:

var brokenJson = function (url) {
    var responseCopy;
    return fetch(url)
    .then(function (response) {
        responseCopy = response.clone();
        return response.json();
    }).catch(function (err) {
        if (err instanceof SyntaxError) {
            return responseCopy.text()
            .then(function(text) {
                console.error(text);
                throw err;
            });
        }
        else {
            throw err;
        }
    }).then(function (json) {
        // do things
    });
};
8
Jaromanda X