I have defined a method to send jquery ajax request like this
sendAjaxRequest(URL, data) {
return $.ajax({
type : 'POST',
url : URL,
crossDomain : true,
data : JSON.stringify(data),
dataType : 'json'
}).fail((responseData) => {
if (responseData.responseCode) {
console.error(responseData.responseCode);
}
});
}
From the place of calling I keep the reference of ajax call
this.ajaxRequest = sendAjaxRequest(Url, data);
and based on user navigation if user navigates away from page ( goes to another page on same website via router ) I want to cancel any pending ajax request.
From the docs I found that jquery jqXHR
object has an abort
method to cancel any ajax request. But in my ajaxRequest
object I don't have any such method available. I am using jquery 2.2 .
For clarification I also want to add that I am using react , and want to achieve this.
componentDidMount: function() {
this.serverRequest = $.get(this.props.source, function (result) {
var lastGist = result[0];
this.setState({
username: lastGist.owner.login,
lastGistUrl: lastGist.html_url
});
}.bind(this));
},
componentWillUnmount: function() {
this.serverRequest.abort();
},
Taken from this link .
They basically say that When fetching data asynchronously, use componentWillUnmount to cancel any outstanding requests before the component is unmounted.
I must be doing something wrong. Any help is appreciated.
According to the ajax documentation , you're doing it properly. The $.ajax()
function returns an object that has an abort
function. You should check for existence of the function because it might not exist if the request has already finished.
componentWillUnmount: function(){
if (this.ajaxRequest && this.ajaxRequest.abort){
this.ajaxRequest.abort()
}
}
Please don't try to abort the AJAX request in this case. The better way is not to do anything if the component is unmounted . Take a look at this:
componentDidMount: function() {
// Register to the handler
this._requestSuccess = this.requestSuccess.bind(this);
$.get(this.props.source, this.requestSuccess);
},
componentWillUnmount: function() {
// "Unregister" by assign it to an empty function
this._requestSuccess = () => {};
},
requestSuccess(lastGist) {
// Do your work
this.setState({
username: lastGist.owner.login,
lastGistUrl: lastGist.html_url
});
},
In the big picture, not just Ajax requests but any async operation inside a component that may change the component's states should be register in componentDidMount
and unregister in componentWillUnmount
, or else you'll find yourself get lost async spaghetti mess.
In the above example, I used this._requestSuccess = ...;
to register and this._requestSuccess = () => {};
to unregister the handler, but in real world application, you'll see people use Flux or Redux to do the same thing.
I highly encourage you to use one of those to manage your application data flow rather than just sending and aborting ajax requests everywhere.
Just have a look on the fiddle . Run the fiddle and check the network tab.
$('button').on('click', function() { var _ajax = $.ajax({ type: 'POST', url: "yourURL", crossDomain: true, data: JSON.stringify('hello'), dataType: 'json' }).fail((responseData) => { if (responseData.responseCode) { console.error(responseData.responseCode); } }); _ajax.abort(); });
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.0/jquery.min.js"></script> <button> Click me </button>
The ajax variable will hold all the ajax related functions as shown in the documentation .
If componentWillUnmount
is not called have a look at your router configuration.
<Route path="/" component={App}>
<IndexRoute component={Home}/>
<Route path="invoices/:invoiceId" component={Invoice}/>
<Route path="accounts/:accountId" component={Account}/>
</Route>
In this example the {App}
component is never unmounted since it's at the root. When you navigate from /invoices/
to /invoices/123
the Invoices component is not unmounted either.
Alternatively you can also tie in to the routers setRouteLeaveHook
like this
import React from 'react';
import { withRouter } from 'react-router';
const MyComponent = React.creatClass({
componentDidMount() {
this.request = $.get( /* ... */ );
this.props.router.setRouteLeaveHook(this.props.route, (request) => {
request.abort();
return true;
});
}
/* .... */
});
export default withRouter(MyComponent);
withRoute
became available in react-router 2.4.0
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.