How to abort pending jquery ajax request when user navigates to other page?

时间:2016-07-11 19:09:28

标签: javascript jquery ajax reactjs

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.

4 个答案:

答案 0 :(得分:5)

根据ajax documentation,您正确地执行了此操作。 $.ajax()函数返回一个具有abort函数的对象。您应该检查函数是否存在,因为如果请求已经完成,它可能不存在。

componentWillUnmount: function(){
  if (this.ajaxRequest && this.ajaxRequest.abort){
    this.ajaxRequest.abort()
  }
}

http://api.jquery.com/jquery.ajax/#jqXHR

答案 1 :(得分:2)

在这种情况下,请不要尝试中止AJAX请求。更好的方法是如果卸载组件则不执行任何操作。看看这个:

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
  });
},

总体而言,不仅仅是Ajax请求,而且更改组件状态的组件内的任何异步操作都应该在componentDidMount和<{1}}中注册 componentWillUnmount中的强>取消注册,否则你会发现自己迷失了异性意粉。

在上面的示例中,我使用this._requestSuccess = ...;注册并this._requestSuccess = () => {};取消注册处理程序,但在实际应用程序中,您会看到人们使用Flux或{{3}做同样的事情。

我强烈建议您使用其中一个来管理您的应用程序数据流,而不是仅仅在任何地方发送和中止Ajax请求。

答案 2 :(得分:1)

只需查看fiddle即可。运行小提琴并检查网络选项卡。

&#13;
&#13;
$('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();
});
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.0/jquery.min.js"></script>
<button>
  Click me
</button>
&#13;
&#13;
&#13;

ajax变量将保存所有与ajax相关的函数,如documentation所示。

答案 3 :(得分:0)

如果未调用num%2,请查看路由器配置。

componentWillUnmount

在此示例中,<Route path="/" component={App}> <IndexRoute component={Home}/> <Route path="invoices/:invoiceId" component={Invoice}/> <Route path="accounts/:accountId" component={Account}/> </Route> 组件永远不会卸载,因为它位于根目录下。当您从{App}导航到/invoices/时,也不会卸载发票组件。

或者您也可以像这样绑定路由器/invoices/123

setRouteLeaveHook

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); 在react-router 2.4.0

中可用