2017-11-23 4 views
2

Das ist der Code ... wie würden Sie einen solchen Ajax-Anruf abbrechen?Wie laufe ich async/abwarte xmlHttpRequest innerhalb von componentWillUnmount ab?

Oder, wie zu verhindern, dass reagieren, mir einen Fehler zu geben "setState aufgerufene unmounted Komponente"?

(HttpGet ist nur ein Wrapper für XMLHttpRequest und ein Versprechen)

async componentDidMount() { 
    const response = await httpGet("/ajaxRequest"); 
    if(response) { 
     //the component has already been unmounted 
     this.setState(() => ({success: true})); 
    } 
} 

componentWillUnmount() { 
    //should abort possible running ajax 
} 

EDIT: Hier ist der Wrapper:

const httpGet = function (url) { 


    const request = new XMLHttpRequest; 
    request.open("GET", url, true); 

    return new Promise((resolve, reject) => { 
     request.onload(response => { 
      resolve(response); 
     }); 

     request.onerror(() => { 
      reject("Network error"); 
     }); 

     request.send(); 
    }); 
}; 
+0

Können wir sehen, wie dieser Wrapper aussieht? –

+0

Wenn Sie die Kontrolle über den Wrapper haben, gibt es ein Muster in der React-Dokumentation beschrieben https://reactjs.org/blog/2015/12/16/ismoverband-antipattern.html – sthzg

+0

@AbdennourTOUMI Ich fügte den Wrapper –

Antwort

3

Um in der Lage sein, es abbrechen, wann immer Sie wollen, XMLHttpRequest Verpackung sollte:

  • Geben Sie entweder das Anfrageobjekt selbst mit dem Versprechen zurück.

  • oder erstellen Sie eine Anfrage außerhalb des Wrappers.

  • Oder verwenden Sie sub/Pub-Bibliothek (wie MUFA oder Redux).

werde ich mit der zweiten Option gehen

const httpGet = function (url, request = new XMLHttpRequest()) { // 2 arguments 

    request.open("GET", url, true); 

    return new Promise((resolve, reject) => { 
     request.onload(response => { 
      resolve(response); 
     }); 

     request.onerror(() => { 
      reject("Network error"); 
     }); 

     request.send(); 
    }); 
}; 

Jetzt in componentDidMount:

async componentDidMount() { 
    this.request = new XMLHttpRequest(); 
    const response = await httpGet("/ajaxRequest", this.request); 
    if(response) { 
     //the component has already been unmounted 
     this.setState(() => ({success: true})); 
    } 
} 

Jetzt in componentWillUnmount:

componentWillUnmount() { 
    if (this.request && this.request.abort) { 
    this.request.abort(); 
    } 
} 

So einfach ist das. Und wenn Sie nicht abbrechen möchten, ist Ihr erster Wrapper (httpGet) noch gültig, da das zweite Argument (Anfrage) optional ist.

+2

genau - ich habe über etwas Ähnliches nachgedacht –

Verwandte Themen