AJAX:Asynchronous JavaScript and XML
Web函数的调用方式
传统的Web函数调用过程完全由浏览器代理,即发起HTTP调用、接收结果和进行本地处理等过程完全由浏览器包办:
- 用户在当前页面点击链接或提交按纽,浏览器作为代理,向服务端发起请求,获得返回的html文档,然后渲染为新页面,并替换掉旧页面
- 从用户角度看,即当前窗口有一个明显地刷新,新页面替代掉了旧页面,地址栏变换为新页面地址
可否允许开发者编写代码来自行发起调用、接收结果和本地处理?
- 用户点击链接或提交按纽,由程序员的脚本作为代理,向服务端发起请求,获得返回的json数据
- 将收到的json数据使用DOM API对当前页面进行操纵
- 从用户角度看,浏览器并不会刷新页面,当前页面只是发生了局部的更新,因此地址栏也不会发生变化。
由用户代码接管Web调用的优劣
- 单页效果:如用户注册流程中,用户名重复导致报错,无需等待整个页面被提交,改善用户体验
- 局部更新:如用户名重复的错误信息直接显示在用户名字段旁,无需刷新整个页面
- 客户端动态页面:可以由客户端生成整个页面,服务端只需提供json数据即可,更为灵活
历史上的尝试:示例说明
下面的Web函数返回一个json数据(可能是静态硬编码或由服务端脚本动态生成),现在如何由程序员编写的脚本进行调用、接收和处理?
// http://x.com/data.json
{"tom":["black",true,1577808000],"cat":["yellow",false,1609430400]}
1577808000, 1609430400 都是Unix时间戳,分别表示 2020-01-01和 2021-01-01
http://x.com/index.html
<script src='./data.json' > // data.json中的内容是数据或字面量(literal),显然并非合法代码,因此js引擎会抛出错误
var data = JSON.parse(???); //
</script>
问题:如何将data.json返回的字符串数据,转换为代码?
解决方案一:以代码的方式载入
http://x.com/data.js
var data = {"tom":["black",true,1577808000],"cat":["yellow",false,1609430400]}
http://x.com/index.html
<script src='/data.js'>
// 由script标记将data.js中的字符串数据转化为js代码
let object = JSON.parse(data); // 这一段代码有必要吗?
</script>
问题:需要服务端和浏览器端共同约定变量名,并且是一个全局变量
解决方案二:以数据方式载入
http://x.com/index.html
let data = fetch("./data.json"); // 假设有一个fetch函数,它读取远程的data.json文件,并将其内容读取为本地的字符串
let object = JSON.parse(data); // => js 对象
问题:如何实现上述fetch函数?
如果你自己编写一个HTTP客户端或浏览器,譬如在移动端原生应用的开发中,你就可以使用HTTP客户端库发起任何调用请求、任意处理响应的数据
解决方案三:巧用 script 标记
http://x.com/data.js
var data = {"tom":["black",true,1577808000],"cat":["yellow",false,7122634433357]};
http://x.com/index.html
function fecth(url){
var s = document.createElement('script');
s.type = 'text/javascript';
s.async = true; //加载方式为异步
s.src = url;
document.getElementsByTagName('body')[0].appendChild(s);
}
fecth('./data.js');
console.log(data.tom)
实际上是方案一的变形,其缺陷仍然是:
- Web函数返回值是文本类型(合法的javascript源代码),而非json数据
- 需要借助全局变量,并且变量命名易存在冲突
AJAX: Asynchronous JavaScript and XML
- AJAX 是由浏览器内生支持的获取服务端的新模式,它允许由程序员编写的js脚本发起请求,接收和处理返回的数据
- 因为服务端函数属于网络资源,故总是以异步的方式进行工作
- 即采用回调函数的方式进行工作
- 程序员通常会采用返回JSON格式数据作为调用的数据格式
- ajax早期使用xml,但后续改为更为简单易用的json
AJAX 示例
http://x.com/data.json
{"tom":["black",true,1577808000],"cat":["yellow",false,7122634433357]};
http://x.com/index.html
$.get("./data.json",function(data,status){
let object = JSON.parse(data);
object.cat[0] = 'white';
// 执行dom更新或其它任意操作
});
简化起见,使用了jquery提供的ajax库,请自行加上对jquery的引用
异步调用 vs. 同步调用
var data = $.get("./data.json"); //同步调用写法,错误!
let object = JSON.parse(data);
object.cat[0] = 'white';
上述代码是错误的,因为Ajax天生只支持异步调用方式,这是由于网络请求是不可靠的,可能成功,也可能不成功(如网络中断、信号不好等),如果使用同步的方式,则意味着限入无限等待,从而形成白屏或卡死等糟糕的用户体验
异步调用的写法是,传入一个函数引用,该函数将会在数据成功返回后被执行,请参考定时器的用法