2017-02-09 3 views
3

Ich habe eine Benutzer-Login-Funktion, die funktioniert. Aber ich möchte einen Timeout-Fehler für den Abruf einbeziehen. Gibt es eine Möglichkeit, einen Timer für 5 Sekunden oder so einzurichten, dass nach einer solchen Zeit aufhören würde zu versuchen, zu holen? Ansonsten bekomme ich nach einer Weile einen roten Bildschirm, der Netzwerkfehler sagt.Einen Timeout-Fehler mit Fetch - Reagieren Native

_userLogin() { 
    var value = this.refs.form.getValue(); 
    if (value) { // if validation fails, value will be null 
    if (!this.validateEmail(value.email)) { 
     Alert.alert(
      "Enter a valid email", 
     ) 
    } else { 
     fetch("http://51.64.34.134:5000/api/login", {  
     method: "POST", 
     headers: { 
      'Accept': 'application/json', 
      'Content-Type': 'application/json' 
     }, 
     timeout: 5000, 
     body: JSON.stringify({ 
      username: value.email, 
      password: value.password, 
     }) 
     }) 
     .then((response) => response.json()) 
     .then((responseData) => { 
     if (responseData.status == "success") { 
     this._onValueChange(STORAGE_KEY, responseData.data.token) 
     Alert.alert(
      "Login Success!", 
     ) 
     this.props.navigator.push({ name: 'StartScreen'}) 
     } else if (responseData.status == "error") { 
     Alert.alert(
      "Login Error", 
      responseData.message 
     ) 
     } 
     }) 
     .done(); 
    } 
    }},  

Antwort

1

Es gibt keine Standardbehandlung wie a timeout option isn't defined in the official spec yet. There is an abort defined die Sie in Verbindung mit Ihrem eigenen Timeout und Promises verwenden können. Zum Beispiel wie gesehen here und here. Ich habe den Beispielcode kopiert, habe es aber selbst noch nicht getestet.

// Rough implementation. Untested. 
function timeout(ms, promise) { 
    return new Promise(function(resolve, reject) { 
    setTimeout(function() { 
     reject(new Error("timeout")) 
    }, ms) 
    promise.then(resolve, reject) 
    }) 
} 

timeout(1000, fetch('/hello')).then(function(response) { 
    // process response 
}).catch(function(error) { 
    // might be a timeout error 
}) 

wäre eine weitere Option, die fetch.js selbst zu modifizieren Modul ein Timeout hinzufügen, die Abbruch here gesehen nennt.

+0

Durch diese Vorgehensweise, es nur Oberfläche der Frage zu lösen, konnte es nicht die Anfrage nach einer bestimmten Zeit abbrechen. – TomSawyer

+0

@ TomSawyer Das war aber nicht gefragt; Die Frage wird nicht nach einem Timeout abgebrochen. Außerdem enthält meine Antwort Links zu möglichen Lösungen für den Abbruch, falls andere in diese Richtung gehen. Also ich bin mir nicht sicher, was der Punkt Ihres Kommentars war? –

+0

Ich habe auf jeden hingewiesen, der sich dafür interessiert, wie ein echter Timeout-Mechanismus funktioniert. In der HTTP-Anfrage bedeutet ein Verbindungs-Timeout, dass die Verbindung abgebrochen wird, ihr zugeordneter Speicher muss freigegeben werden, ihr Prozess muss beendet werden, nicht nur false für das ui-Update zurückgegeben werden, sondern weiter im Hintergrund ausgeführt werden. – TomSawyer

0

Ich löste dieses Problem mit einem Rennen zwischen zwei Versprechen, geschrieben als Wrapper um Fetch. In meinem Fall erwarte ich die Anfrage, json zurückzugeben, so fügte auch das hinzu. Vielleicht gibt es eine bessere Lösung, aber das funktioniert für mich richtig!

Der Wrapper gibt ein Versprechen zurück, das behoben wird, solange keine Codefehler vorliegen. Sie können den result.status auf 'success' prüfen und json-Daten aus result.data lesen. Im Falle eines Fehlers können Sie den genauen Fehler in result.data lesen und ihn anzeigen oder irgendwo aufzeichnen. Auf diese Weise wissen Sie immer, was schief gelaufen ist!

var yourFetchWrapperFunction = function(method, url, headers, body, timeout=5000){  
var timeoutPromise = new Promise(function(resolve,reject){ 
         setTimeout(resolve, timeout, {status: 'error', code: 666, data: 'Verbinding met de cloud kon niet tot stand gebracht worden: Timeout.'}); 
         }); 
    return Promise.race([timeoutPromise, fetch(connectionType + '://' + url, {method: method, headers: headers, body: body})]).then((result) => { 
         var Status = result.status; 
         return result.json().then(function(data){ 
          if (Status === 200 || Status === 0) { 
          return {status: 'success', code: Status, data: data}; 
          } 
          else { 
          return {status: 'error', code: Status, data: 'Error (' + data.status_code + '): ' + data.message}; 
          } 
         },function (response) { 
          return {status: 'error', code: Status, data: 'json promise failed' + response}; 
         }).catch((error) => { 
          return {status: 'error', code: 666, data: 'no json response'}; 
         }); 
         }, function(error){ 
          return {status: 'error', code: 666, data: 'connection timed out'}; 
         }).catch((error) => { 
          return {status: 'error', code: 666, data: 'connection timed out'}; 
         }); 
} 
0

Dies ist, was ich um es zu gehen hat: (Die die „generische“ Funktion ist verwende ich alle Anrufe auf meine App zu machen)

Ich habe eine Timeout-Funktion, die ausgelöst wird, es sei denn, es ist vorher gelöscht, dann lösche ich dieses Timeout auf Server Antwort