Abrufen gibt einen leeren Antworttext

73

Ich habe eine React / Redux-Anwendung und versuche, eine einfache GET-Anfrage an einen Server zu senden:

fetch('http://example.com/api/node', {
  mode: "no-cors",
  method: "GET",
  headers: {
    "Accept": "application/json"
  }
}).then((response) => {
  console.log(response.body); // null
  return dispatch({
    type: "GET_CALL",
    response: response
  });
})
.catch(error => { console.log('request failed', error); });

Das Problem ist, dass der Antworttext in der .then()Funktion leer ist und ich nicht sicher bin, warum. Ich habe Beispiele online überprüft und es sieht so aus, als ob mein Code funktionieren sollte, sodass mir hier offensichtlich etwas fehlt. Die Sache ist, wenn ich die Registerkarte "Netzwerk" in den Entwicklertools von Chrome überprüfe, wird die Anfrage gestellt und ich erhalte die Daten, nach denen ich suche.

Kann jemand ein Licht auf dieses werfen?

BEARBEITEN:

Ich habe versucht, die Antwort zu konvertieren.

mit .text():

fetch('http://example.com/api/node', {
  mode: "no-cors",
  method: "GET",
  headers: {
    "Accept": "application/json"
  }
})
.then(response => response.text())
.then((response) => {
  console.log(response); // returns empty string
  return dispatch({
    type: "GET_CALL",
    response: response
  });
})
.catch(error => { console.log('request failed', error); });

und mit .json():

fetch('http://example.com/api/node', {
  mode: "no-cors",
  method: "GET",
  headers: {
    "Accept": "application/json"
  }
})
.then(response => response.json())
.then((response) => {
  console.log(response.body);
  return dispatch({
    type: "GET_CALL",
    response: response.body
  });
})
.catch(error => { console.log('request failed', error); }); // Syntax error: unexpected end of input

In den Chrome Dev Tools suchen:

Geben Sie hier die Bildbeschreibung ein

Razvan Ilin
quelle
Ich konnte mich nicht fetchan die Arbeit machen und begann mit der Redux-API-Middleware . Wenn Sie die Anfrage stellen, müssen Sie die Antwort auf ähnliche Weise in json konvertieren, wie die Leute hier vorgeschlagen haben:
Razvan Ilin

Antworten:

159

Ich bin gerade darauf gestoßen. Wie in dieser Antwort erwähnt , erhalten Sie mit using mode: "no-cors"eine opaque response, die anscheinend keine Daten im Körper zurückgibt.

undurchsichtig: Antwort auf "No-Cors" -Anforderung an eine Cross-Origin-Ressource. Stark eingeschränkt .

In meinem Fall habe ich verwendet Express. Nachdem ich cors for Express installiert und konfiguriert und entfernt hatte mode: "no-cors", wurde mir ein Versprechen zurückgegeben. Die Antwortdaten werden im Versprechen sein, z

fetch('http://example.com/api/node', {
  // mode: 'no-cors',
  method: 'GET',
  headers: {
    Accept: 'application/json',
  },
},
).then(response => {
  if (response.ok) {
    response.json().then(json => {
      console.log(json);
    });
  }
});
RationalDev mag GoFundMonica
quelle
3
Für mich war alles, was erforderlich war, .then(json => {das Ende meiner response.json()Aussage hinzuzufügen . Vielen Dank!
Mike Kellogg
2
@MikeKellogg ist nur ein Hinweis darauf, dass Sie return response.json()den .then(json=>Teil zwischen der letzten Klammer und dem Semikolon platzieren können, falls Sie Ihren Code aufgeräumt halten möchten . ).then(json=>{});
Razvan Ilin
Es scheint, wenn Sie die Domain verlassen und eine relative URI verwenden, mit der sie funktioniertno-cors
Danny '365CSI' Engelman
29

Sie müssen Ihre responsein konvertieren , jsonbevor Sie darauf zugreifen könnenresponse.body

Aus den Dokumenten

fetch(url)
  .then(response => response.json())
  .then(json => {
    console.log('parsed json', json) // access json.body here
  })
Naisheel Verdhan
quelle
6

Sie müssen den Text der Antwort lesen:

fetch(url)
  .then(res => res.text()) // Read the body as a string

fetch(url)
  .then(res => res.json()) // Read the body as JSON payload

Sobald Sie den Körper gelesen haben, können Sie ihn manipulieren:

fetch('http://example.com/api/node', {
  mode: "no-cors",
  method: "GET",
  headers: {
    "Accept": "application/json"
  }
})
  .then(response => response.json())
  .then(response => {
    return dispatch({
      type: "GET_CALL",
      response: response
    });
  })
Florent
quelle
Danke für die Antwort! Ich habe das versucht, aber ich kann immer noch die richtige Antwort bekommen. Überprüfen Sie die bearbeitete Frage.
Razvan Ilin
@ RasvanIlin Verwenden Sie .json()anstelle von.text()
Florent
1
Entschuldigung, ich habe gerade festgestellt, dass ich im letzten Beispiel das falsche Snippet kopiert habe. Ich habe es tatsächlich verwendet json(), aber ich erhalte den Syntaxfehler, der vermutlich ausgelöst wird, weil er die Antwort nicht in json konvertieren kann
Razvan Ilin
Versuchte dies und es funktionierte für mich. response.json()tat die Magie. Sobald ich es hatte, konnte ich console.log und meine Antwort erhalten. Danke
Hanmaslah
3
Ich versuche immer noch, meinen Kopf um diesen no-corsModus zu wickeln . Ich bin in einer ähnlichen Situation. Bei Verwendung von Variationen der Lösungen hier scheint der No-Cors-Abruf erfolgreich zu sein ... kein x-origin-Fehler, und in meinem Netzwerkinspektor kann ich Daten in Vorschau und Antwort SEHEN. Aber ich kann einfach nicht auf die Daten des Antwortobjekts zugreifen, das an mein übergeben wurde then. json() text()keiner scheint viel zu tun. Bedeutet eine undurchsichtige Antwort, dass die Daten nullabgerufen werden und nach Abschluss nicht mehr darauf zugegriffen werden kann? : - /
jmk2142
4
fetch("http://localhost:8988/api", {
        //mode: "no-cors",
        method: "GET",
        headers: {
            "Accept": "application/json"
        }
    })
    .then(response => {
        return response.json();
    })
    .then(data => {
        return data;
    })
    .catch(error => {
        return error;
    });

Das funktioniert bei mir.

Ani Thettayil
quelle
3
fetch("http://localhost:8988/api", {
    method: "GET",
    headers: {
       "Content-Type": "application/json"
    }
})
.then((response) =>response.json());
.then((data) => {
    console.log(data);
})
.catch(error => {
    return error;
});

quelle
2
Während dieser Code die Frage des OP beantworten kann, würden ein paar erklärende Worte einen großen Beitrag dazu leisten, dass aktuelle und zukünftige Leser Ihre Antwort verstehen.
Thom
Dies ist tatsächlich ein sehr ähnliches Beispiel wie andere Antworten hier. Ich bin mir nicht sicher über die Richtlinien von SO, aber ich bin mir nicht sicher, ob dies erlaubt ist
Razvan Ilin
Nur ist es nicht dasselbe. "Content-Type" ist einzigartig. Schade, dass es bei mir nicht funktioniert hat :(
Michael
2

Versuchen Sie, response.json () zu verwenden :

fetch('http://example.com/api/node', {
  mode: "no-cors",
  method: "GET",
  headers: {
    "Accept": "application/json"
  }
}).then((response) => {
  console.log(response.json()); // null
  return dispatch({
    type: "GET_CALL",
    response: response.json()
  });
})
.catch(error => { console.log('request failed', error); });
Damien Leroux
quelle
1

Dies erfordert Änderungen am Frontend-JS und den vom Backend gesendeten Headern.

Vorderes Ende

Entfernen Sie "mode":"no-cors"in den Abrufoptionen.

fetch(
  "http://example.com/api/docs", 
  {
    // mode: "no-cors",
    method: "GET"
  }
)
  .then(response => response.text())
  .then(data => console.log(data))

Backend

Wenn Ihr Server auf die Anfrage antwortet, fügen Sie die CORS-Header hinzu, die den Ursprung angeben, von dem die Anfrage kommt. Wenn Sie sich nicht für den Ursprung interessieren, geben Sie den *Platzhalter an.

Die Rohantwort sollte einen solchen Header enthalten.

Access-Control-Allow-Origin: *
openwonk
quelle
0

In vielen Fällen müssen Sie das bodyParser-Modul in Ihrer Express Node-App hinzufügen. Fügen Sie dann in Ihrem App.use-Teil unten app.use(express.static('www')); diese 2 Zeilen hinzu app.use(bodyParser.urlencoded({ extended: true })); app.use(bodyParser.json());

Brianhenry
quelle