一、ajax
-
Ajax 全称为:“Asynchronous JavaScript and XML”(异步 JavaScript 和 XML),它并不是 JavaScript 的一种单一技术,而是利用了一系列交互式网页应用相关的技术所形成的结合体。使用Ajax,我们可以无刷新状态更新页面,并且实现异步提交,提升了用户体验。
-
Ajax 这个概念是由 JesseJamesGarrett 在 2005 年发明的。它本身不是单一技术,是一串技术的集合,主要有:
- JavaScript,通过用户或其他与浏览器相关事件捕获交互行为
- XMLHttpRequest 对象,通过这个对象可以在不中断其它浏览器任务的情况下向服务器发送请求;
- 服务器上的文件,以 XML、HTML 或 JSON 格式保存文本数据;
- 其它 JavaScript,解释来自服务器的数据(比如 PHP 从 MySQL 获取的数据)并将其呈现到页面上。 -
由于 Ajax 包含众多特性,优势与不足也非常明显。优势主要以下几点:
- 不需要插件支持(一般浏览器且默认开启 JavaScript 即可);
- 用户体验极佳(不刷新页面即可获取可更新的数据);
- 提升 Web 程序的性能(在传递数据方面做到按需发送,不必整体提交);
- 减轻服务器和带宽的负担(将服务器的一些操作转移到客户端); -
而 Ajax 的不足由以下几点:
1.不同版本的浏览器对 XMLHttpRequest 对象支持度不足(比如 IE5 之前);
2.前进、后退的功能被破坏(因为 Ajax 永远在当前页,不会记录前后页面);
3.搜索引擎的支持度不够(因为搜索引擎爬虫还不能理解 JS 引起变化数据的内容);
二、jsonp
- 我们在了解什么是jsonp之前,我们要先了解什么是跨域。简单来说,跨域就是当没有遵守同源策略时,ajax请求会报:请求的资源上不存在“访问控制允许源”标头。那什么是同源策略呢?同协议,同域名,同端口就是同源策略。
- 跨域的解决方案有哪些:
- 不允许ajax发起跨域请求,不用ajax(使用jsonp)
- 不允许请求没有明确允许的资源,设置明确允许(CORS跨域)
- 浏览器会阻止没有明确允许的资源,干掉浏览器(服务器代理) - jsonp的原理:利用script标签不会触发浏览器的同源策略,及script标签将自身引用的数据,作为js代码执行的原理。配合函数的传参(执行时的参数发送给定义时的参数),实现跨域数据的获取。
三、封装ajax和jsonp
1. 思路
- 执行函数要传参,传的有:
类型(可设默认值),
url,
请求成功返回值,
请求失败(可选),
要发送的数据(当类型为jsonp时,必传)等。因为过多,所以可以写成一个对象
超时timeout
是否异步(可设默认值) - 开始封装request
- 传参,函数要接收参数,因为接收的是一个对象,需要拿到每一个对象的数据,解构赋值就会很方便了。并设置默认值
- 首先不管是get/post还是jsonp都要处理数据。
- url是只有post不需要拼接,所以if不是post,就拼接一个url
- ajax发送数据,创建xhr对象;get和post的是除了xhr.send不一样之外,其余都一样,因此就if一个不是jsonp,创建xhr对象
- 进行xhr.send()的区分,if是get,else是post
- 如果type不是jsonp的话,程序需要到此结束
- 以上就是post和get的封装,然后 如果是jsonp的话,以上的if就不会执行,程序还在继续
- 执行jsonp
- 所有请求的超时的设置:因为函数中存在return,又需要保证当前超时的延时器,必须执行,所以将延时器的代码放在上面。
- 因为是异步的程序,所以只要执行结束,就得立即确定一个状态,并清空其他状态。
2. 代码实现
function request(ops){
let {
type="get",
url,
data={},
success,
error,
timeout=1000,
async=true
} = ops;
let str = "";
for(let i in data){
str += `${i}=${data[i]}&`;
}
if(type !== "post"){
url = url + "?" + str + "__qft__=" + Date.now();
}
setTimeout(() => {
error && error("timeout");
success = null;
error = null;
}, timeout);
let xhr;
if(type !== "jsonp"){
xhr = new XMLHttpRequest();
xhr.open(type, url, async);
xhr.onload = function(){
if(xhr.status === 200){
success && success(xhr.responseText);
success = null;
error = null;
}else{
error && error(xhr.status);
success = null;
error = null;
}
}
if(type === "get"){
xhr.send()
}else{
xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
xhr.send(str.slice(0,str.length-1));
}
return;
}
let script = document.createElement("script");
script.src = url;
document.body.appendChild(script);
window[data[data.cn]] = function(res){
success && success(res);
success = null;
error = null;
}
}