Dynamic Static

Jaron的博客 - 关于代码及其他

Fork me on GitHub

jQuery JSONP请求的错误处理

jQuery的ajax方法封装的非常好,使用它你可以非常轻松的编写异步请求代码,但如果你是用它来做JSONP跨域请求,那你可要注意了,此处有坑!

以下是常见的jqeury jsonp请求的代码:

1
2
3
4
5
6
7
8
9
10
11
12
$.ajax({
  url: 'https://api.github.com/users/jarontai/repos',
  type: 'GET',
  dataType: 'jsonp', // dataType为jsonp
  success: function(data) {
      $('.result').text(JSON.stringify(data));
  },
  error: function(jqXHR, textStatus) {
      $('.result').text('error');
      alert('JSONP error!');
  }
});

以上方法看似安全可行,但如果你把url参数改成某个不存在的地址,你会惊奇的发现:虽然浏览器终端报出错误(404或其他网络错误),但你的error回调却没有被执行!?



这是为什么呢?我们仔细看看ajax方法的文档,在它error回调说明的最后有一句话:

1
Note: This handler is not called for cross-domain script and cross-domain JSONP requests. This is an Ajax Event.

这句话的意思是在调用跨域的脚本及JSONP请求时,这个错误回调将不会被执行,并强调指出这个error是一个 Ajax Event.

什么意思?难道说jsonp不是ajax?

是的,严格意义上来说jsonp不是ajax,ajax是通过XMLHttpRequest对象发送异步请求,而jsonp则是利用js标签天生具备的跨域能力来实现跨域资源访问。也就是说,虽然它的名字叫JSONP(JSON with Padding),但它底层是通过js标签实现的,它跟json以及普通异步请求关系都不大,jquery之所以把jsonp请求放到ajax方法里面,只是为了让api更方便调用而已。 (JSONP的详细描述可以查看WIKI,或者google)



那怎么做才能使JSONP的error回调被执行呢?

有两个方法,方法一:添加timeout参数。

1
2
3
4
5
6
7
8
9
10
11
12
13
$.ajax({
  url: 'https://api.github.com/users/jarontai/repos',
  type: 'GET',
  dataType: 'jsonp', // dataType为jsonp
  timeout: 5000, // 添加timeout参数        
  success: function(data) {
      $('.result').text(JSON.stringify(data));
  },
  error: function(jqXHR, textStatus) { // 此时textStatus为‘timeout’
      $('.result').text('error');
      alert('JSONP error!');
  }
});

添加timeout参数后,虽然JSONP请求本身的错误没有被捕获,但是最终会因为超时而执行error回调。



那还有没有方法使error回调在JSONP错误发生时就执行呢?

方法二出场:使用jquery jsonp插件 - https://github.com/jaubourg/jquery-jsonp

以下为常见的jqeury jsonp插件调用代码:

1
2
3
4
5
6
7
8
9
10
11
12
$.jsonp({
  url: 'https://api.github.com/users/jarontai/repos',
  callbackParameter: "callback",
  timeout: 5000,
  error: function(xOptions, textStatus) { // 错误发生时,立即执行
      $('.result').text('error');
      alert('JSONP error!');
  },
  success: function(data) {
      $('.result').text(JSON.stringify(data));
  }
});

使用jsonp插件,能够在错误发生时立即执行error回调,并且还附带如’数据过滤’等功能,更多详细介绍请查看它的主页。

以上。

评论