天天看点

原生 JavaScript 实现 AJAX、JSONP

相信大多数前端开发者在需要与后端进行数据交互时,为了方便快捷,都会选择​<code>​JQuery​</code>​中封装的​<code>​AJAX​</code>​方法,但是有些时候,我们只需要​<code>​JQuery​</code>​的​<code>​AJAX​</code>​请求方法,而其他的功能用到的很少,这显然是没必要的。 

其实,原生​<code>​JavaScript​</code>​实现​<code>​AJAX​</code>​并不难,这篇文章将会讲解如何实现简单的​<code>​AJAX​</code>​,还有跨域请求​<code>​JSONP​</code>​! 

一、AJAX 

AJAX的核心是​<code>​XMLHttpRequest​</code>​。 

一个完整的​<code>​AJAX​</code>​请求一般包括以下步骤:

实例化​<code>​XMLHttpRequest​</code>​对象

连接服务器

发送请求

接收响应数据

我将​<code>​AJAX​</code>​请求封装成​<code>​ajax()​</code>​方法,它接受一个配置对象​<code>​params​</code>​。

在上面的代码中,已经添加具体的注释,如需了解更多​<code>​AJAX​</code>​,可查看博主的书籍《 JavaScript半知半解》中的 ​<code>​AJAX​</code>​章节:AJAX 

使用实例:

二、JSONP 

同源策略 

AJAX之所以需要“跨域”,罪魁祸首就是浏览器的 ​<code>​同源策略​</code>​。即,一个页面的AJAX只能获取这个页面相同源或者相同域的数据。 如何叫“同源”或者“同域”呢?——​<code>​协议、域名、端口号都必须相同​</code>​。例如:

当跨域请求时,一般都会看到这个错误: ​<code>​XMLHttpRequest cannot load http://ghmagical.com/article/?intro=jsonp%E8%AF%B7%E6%B1%82&amp;v=5520. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost' is therefore not allowed access.​</code>​

那如何跨域请求呢?这时,JSONP就登场了! 

JSONP(JSON with Padding) 是一种跨域请求方式。主要原理是利用了​<code>​script ​</code>​标签可以跨域请求的特性,由其 ​<code>​src​</code>​ 属性发送请求到服务器,服务器返回 ​<code>​JavaScript ​</code>​代码,浏览器接受响应,然后就直接执行了,这和通过 ​<code>​script​</code>​ 标签引用外部文件的原理是一样的。

JSONP由两部分组成:​<code>​回调函数​</code>​和​<code>​数据​</code>​,回调函数一般是在浏览器控制,作为参数发往服务器端(当然,你也可以固定回调函数的名字,但客户端和服务器端的名称一定要一致)。当服务器响应时,服务器端就会把该函数和数据拼成字符串返回。 

JSONP的请求过程:

请求阶段:浏览器创建一个 ​<code>​script​</code>​ 标签,并给其​<code>​src​</code>​ 赋值(类似 ​<code>​http://example.com/api/?callback=jsonpCallback​</code>​ )。

发送请求:当给​<code>​script​</code>​的​<code>​src​</code>​赋值时,浏览器就会发起一个请求。

数据响应:服务端将要返回的​<code>​数据​</code>​作为参数和​<code>​函数名称​</code>​拼接在一起(格式类似”​<code>​jsonpCallback({name: 'abc'})​</code>​”)返回。当浏览器接收到了响应数据,由于发起请求的是 ​<code>​script​</code>​,所以相当于直接调用 ​<code>​jsonpCallback​</code>​ 方法,并且传入了一个参数。

对于​<code>​JQuery​</code>​的JSONP请求,这里就不多讲了,之前也写过一篇文章《JQuery的Ajax请求跨域问题》。 

在这里讲解一下用原生​<code>​JavaScript​</code>​如何实现。 

依旧是​<code>​ajax()​</code>​方法里添加JSONP,后面会将两者整合在一起,JSONP的配置参数主要多了一个​<code>​jsonp​</code>​参数,它就是你的回调函数名。

注意:因为 ​<code>​script​</code>​ 标签的​<code>​ src​</code>​ 属性只在第一次设置的时候起作用,导致 ​<code>​script​</code>​ 标签没法重用,所以每次完成操作之后要移除; 

在这里后台使用PHP处理:

注意:别漏了用函数名与数据拼接返回。 

当然,前面也说过,你可以给定固定回调函数名: