Native reagieren: Mögliche Ablehnung von unbehandelten Versprechungen

78

Ich erhalte die folgende Fehlermeldung: Possible unhandled promise rejection (id:0: Network request failed

Hier ist der Versprechen-Code, ich sehe nicht, was hier falsch ist, irgendwelche Ideen?

  return fetch(url)
    .then(function(response){
      return response.json();
    })
    .then(function(json){
      return {
        city: json.name,
        temperature: kelvinToF(json.main.temp),
        description: _.capitalize(json.weather[0].description)
      }
    })
    .catch(function(error) {
    console.log('There has been a problem with your fetch operation: ' + error.message);
    });
}

** Bearbeiten: Ich habe eine Fangfunktion hinzugefügt und einen besseren Fehler erhalten You passed an undefined or null state object; instead, use forceUpdate(). index.ios.js:64 undefined

Hier ist der index.ios.js Code. Die URL ist in Ordnung und gibt mir die richtigen JSON-Daten. Ich kann mit dem Konsolenprotokoll sehen, dass beide region.latitudeund region.longitudein verfügbar sind Api(region.latitude, region.longitude). Ist dataaber undefiniert. Ich bin mir immer noch nicht sicher, was los ist, warum es ein Problem gibt dataund warum es undefiniert ist.

// var React = require('react-native'); --deprecated

// updated
import React from 'react';

// updated
import {
  AppRegistry,
  MapView,
  View,
  Text,
  StyleSheet,
} from 'react-native';

/*
var {
  AppRegistry,
  MapView,
  View,
  Text,
  StyleSheet
} = React;
*/ // -- depreciated 


var Api = require('./src/api');

var Weather = React.createClass({
  getInitialState: function() {
    return {
      pin: {
        latitude: 0,
        longitude: 0
      },
      city: '',
      temperature: '',
      description: ''
    };
  },
  render: function() {
    return <View style={styles.container}>
      <MapView
        annotations={[this.state.pin]}
        onRegionChangeComplete={this.onRegionChangeComplete}
        style={styles.map}>
      </MapView>
      <View style={styles.textWrapper}>
        <Text style={styles.text}>{this.state.city}</Text>
        <Text style={styles.text}>{this.state.temperature}</Text>
        <Text style={styles.text}>{this.state.description}</Text>
      </View>
    </View>
  },
  onRegionChangeComplete: function(region) {
    this.setState({
      pin: {
        longitude: region.longitude,
        latitude: region.latitude
      }
    });

    Api(region.latitude, region.longitude)
      .then((data) => {
        console.log(data);
        this.setState(data);
      });
  }
});




var styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'stretch',
    backgroundColor: '#F5FCFF'
  },
  map: {
    flex: 2,
    marginTop: 30
  },
  textWrapper: {
    flex: 1,
    alignItems: 'center'
  },
  text: {
    fontSize: 30
  }
});

AppRegistry.registerComponent('weather', () => Weather);
Agent Zebra
quelle
3
Fügen Sie .catch()auch hinzu und prüfen Sie, ob der Fehler verschwindet. Referenz: facebook.github.io/react-native/docs/…
Ivan Chernykh
1
Vielen Dank. einfach .catch (err => err) bis nach .then () für mich gearbeitet hat. =)
Noby Fujioka

Antworten:

53

Die catch-Funktion in Ihrer API sollte entweder einige Daten zurückgeben, die vom Api-Aufruf in der React-Klasse verarbeitet werden könnten, oder einen neuen Fehler auslösen, der mithilfe einer catch-Funktion in Ihrem React-Klassencode abgefangen werden sollte. Letzterer Ansatz sollte ungefähr so ​​aussehen:

return fetch(url)
.then(function(response){
  return response.json();
})
.then(function(json){
  return {
    city: json.name,
    temperature: kelvinToF(json.main.temp),
    description: _.capitalize(json.weather[0].description)
  }
})
.catch(function(error) {
console.log('There has been a problem with your fetch operation: ' + error.message);
 // ADD THIS THROW error
  throw error;
});

Dann in Ihrer Reaktionsklasse:

Api(region.latitude, region.longitude)
  .then((data) => {
    console.log(data);
    this.setState(data);
  }).catch((error)=>{
     console.log("Api call error");
     alert(error.message);
  });
while1
quelle
1
Vielen Dank, ich habe die catch-Funktion auch in der API hinzugefügt und es wird kein Fehler ausgegeben. Seltsam.
Agent Zebra
1
Haben Sie nach console.log einen Wurffehler hinzugefügt ('Es ist ein Problem mit Ihrer Abrufoperation aufgetreten:' + error.message); in Ihrer Fetch-Catch-Funktion. Siehe Wurffehler im ersten Snippet hinzugefügt.
während1
Ah je, das habe ich verpasst, danke. Der Fehler ist Network request failed, das ist der gleiche Fehler, den ich am Anfang bekommen habe. Hmm ... immer noch nicht sicher, was hier los ist.
Agent Zebra
Irgendeine Idee, warum ich immer noch einen Network request failedFehler bekomme ?
Agent Zebra
1
Ich denke, das Problem liegt in Ihrer URL-Anfrage. Nicht in naiv reagieren wo. Versuchen Sie, die API-URL in der Simulatorsafari zu öffnen, um sicherzustellen, dass der Simulator auf die URL zugreifen kann. Stellen Sie außerdem sicher, dass Ihre App-Transportrichtlinie einen http-Anruf zulässt. Siehe dazu stackoverflow.com/questions/31254725/… .
während1
3

Sie sollten den catch () am Ende des Api-Aufrufs hinzufügen. Wenn Ihr Code auf catch () trifft, gibt er nichts zurück, sodass die Daten nicht definiert sind, wenn Sie versuchen, setState () darauf zu verwenden. Die Fehlermeldung sagt dir das auch :)

Hassio
quelle
Vielen Dank, ich habe die catch-Funktion auch in der API hinzugefügt und es wird kein Fehler ausgegeben. Seltsam.
Agent Zebra
In Bezug auf den Netzwerkfehler ... führen Sie den Abruf in einem Emulator aus? Möglicherweise kann es aufgrund einer Firewall auf Ihrem lokalen Entwicklungscomputer nicht auf das Netzwerk zugreifen? Oder vielleicht können die Android-DNS die URL nicht auflösen - versuchen Sie es also mit einer IP-Adresse.
Hassio
Ja, es läuft im iOS-Simulator, keine Firewall. Wie versuche ich es mit einer IP-Adresse?
Agent Zebra
Bearbeiten: Entschuldigung, habe gerade die ios-Anforderung gesehen ... versuchen Sie diese Antwort - stackoverflow.com/questions/13542706/…
hatio
Hey kein Problem, danke. Ich habe es versucht, habe nicht geholfen :(
Agent Zebra
3

Laut diesem Beitrag sollten Sie es in XCode aktivieren.

  1. Klicken Sie im Projektnavigator auf Ihr Projekt
  2. Öffnen Sie die Registerkarte Info
  3. Klicken Sie auf den Abwärtspfeil links neben "App Transport Security Settings".
  4. Klicken Sie mit der rechten Maustaste auf "Sicherheitseinstellungen für den App-Transport" und wählen Sie Zeile hinzufügen
  5. Setzen Sie für die erstellte Zeile den Schlüssel „Allow Arbitrary Loads“, lassen Sie boolean und den Wert YES ein.

Geben Sie hier die Bildbeschreibung ein

Didier Emmanuel Derozin
quelle
3

Fügen Sie hier meine Erfahrung hinzu, die hoffentlich jemandem helfen könnte.

Ich hatte das gleiche Problem mit dem Android-Emulator unter Linux beim Hot-Reload. Der Code war gemäß der akzeptierten Antwort korrekt und der Emulator konnte das Internet erreichen (ich brauchte einen Domainnamen).

Durch manuelles Aktualisieren der App funktionierte sie. Vielleicht hat es etwas mit dem heißen Nachladen zu tun.

Stillleben
quelle
1

Build-Ordner löschen projectfile\android\app\buildund Projekt ausführen

Mahdi Pourrostam
quelle
0

In meinem Fall verwende ich ein lokales Django-Backend in IP 127.0.0.1:8000 mit Expo-Start. public domainStellen Sie einfach sicher, dass der Server nicht lokal auf Ihrem Computer gehostet ist

Arun K.
quelle