Murat Ogulcan Sahin
Murat Ogulcan Sahin

Reputation: 142

Why is my PATCH request's response empty ? (Javascript)

I have an app runs Rails in backend, Javascript frontend. My controllers, routes and CORS is fine. My Post and Get requests are working fine. However when I make a patch request, it successfully does patching but as response.text(), I get empty string. So when I use response.json(), it gives me Uncaught (in promise) SyntaxError: Unexpected end of JSON input at game.js:25 error. I need to know the source of the problem.

static patchGame() {
        const numberOfClicks = parseInt(document.getElementById('click-number').textContent, 10)
        const score = parseInt(document.getElementById('score').textContent,10)
        const gameID = document.getElementById('gameID').value
        const gameObj = {game: {click_number: numberOfClicks, score: score}}
        const options = {
            method: "PATCH",
            headers: {"Content-Type": "application/json",
                      "Accept": "application/json"},
            body: JSON.stringify(gameObj)
        }
            fetch(`http://localhost:3000/games/${gameID}`, options).then(resp => {debugger}).then(game => { debugger }) // NEVER HITS last debugger    
    }

These are the resp debugger values I get,

>resp

<-Response {type: "cors", url: "http://localhost:3000/games/28", redirected: false, status: 204, ok: true, …}
body: ReadableStream
bodyUsed: false
headers: Headers {}
ok: true
redirected: false
status: 204
statusText: "No Content"
type: "cors"
url: "http://localhost:3000/games/28"
__proto__: Response



>resp.text()

<-Promise {<pending>}
__proto__: Promise
[[PromiseState]]: "pending"
[[PromiseResult]]: undefined


>resp.json()

<-Promise {<rejected>: TypeError: Failed to execute 'json' on 'Response': body stream already read
    at eval (eval at <a…}
__proto__: Promise
[[PromiseState]]: "rejected"
[[PromiseResult]]: TypeError: Failed to execute 'json' on 'Response': body stream already read at eval (eval at <anonymous> (file:///Users/muratogulcansahin/Desktop/DanceMemory/frontend/game.js:1:1), <anonymous>:1:6) at file:///Users/muratogulcansahin/Desktop/DanceMemory/frontend/game.js:24:84
message: "Failed to execute 'json' on 'Response': body stream already read"
stack: "TypeError: Failed to execute 'json' on 'Response': body stream already read\n    at eval (eval at <anonymous> (file:///Users/muratogulcansahin/Desktop/DanceMemory/frontend/game.js:1:1), <anonymous>:1:6)\n    at file:///Users/muratogulcansahin/Desktop/DanceMemory/frontend/game.js:24:84"
__proto__: Error



>resp.body

<-ReadableStream {locked: true}
locked: true
__proto__: ReadableStream

Upvotes: 0

Views: 1767

Answers (2)

gear4
gear4

Reputation: 844

NOTE: I had mis-read the question, and only went on debugger values instead of reading the question fully. This is the correct answer to the question: https://stackoverflow.com/a/67453072/1710359. I will leave this answer as-is in case someone else has this issue too.

ORIGINAL ANSWER:

The code that fails is not in the code that was provided.

This is caused by using .json() multiple times, and is (I assume) located within that second .then() call.

Please revise your code and make sure you only call .json() one time per request, as .json() consumes the resulting body.

You are able to monitor if the body has been consumed by using the .bodyUsed variable, which is available in any fetch response.

This is an explanation based on your own debugger logs:

>resp 

<-Response {type: "cors", url: "http://localhost:3000/games/28", redirected: 
// prints your server's response data (resp.bodyUsed is now *false*)


>resp.text()

<-Promise {<pending>}
// prints your server's response data as *text*, and *consumes* the body (resp.bodyUsed is now *true*)


>resp.json()

<-Promise {<rejected>: TypeError: Failed to execute 'json' on 'Response': body
// fails to print your server's response data, because you have *already* consumed the body by using `.text()`

Upvotes: 1

Damilare Olusakin
Damilare Olusakin

Reputation: 439

it looks like there is a 204 response, which is what I'd expect from a successful PATCH, meaning no content is being returned from the server. That would certainly explain the issues you are having with this.

Basically, I won't expect to be able to call .text() or more specifically .json() on the absent content.

Ideally, PUT and PATCH requests are not expected to return data. 200s are acceptable but 204s are the most appropriate in my honest opinion

Upvotes: 3

Related Questions