js与ajax中异步调用的简单理解
Posted 菜菜粥
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了js与ajax中异步调用的简单理解相关的知识,希望对你有一定的参考价值。
这个两段代码是在同一个js文件中
function connectServer(callback)
if (window.XMLHttpRequest)
xmlhttp = new XMLHttpRequest();
else if (window.ActiveXObject)
xmlHttp = new ActiveXObject("Microsoft.XMLHttp");
else return;
xmlhttp.onreadystatechange = function()
if (xmlhttp.readyState == 4 && xmlhttp.status == 200)
callback(xmlhttp.responseText);
// 这里是异步调用的模式
// 这里的server是用node启动的服务端脚本,返回一个随机数
xmlhttp.open('GET', '../server', true);
xmlhttp.send();
下面这里是为一个button触发Click时间时请求一个随机数并写入内部的元素内容中
buttons[i].onclick = function(i)
return function()
if (this.disabled) return;
bannedButtons(this, buttons);
this.childNodes[1].innerhtml = '...';
this.childNodes[1].style.visibility = 'visible';
connectServer(function(data)
buttons[i].childNodes[1].innerHTML = data;
bannedButtons(null, buttons);
enableButtons(buttons);
checkInfoIsReady(buttons);
);
(i);
为什么connectServer(function(data) ….会是异步调用呢
先看些其他的
for (var i = 0; i < 5; i++)
buttons[i].onclick = function()
return function ()
console.log(i);
;
这种形式是事件触发的时候是 return内层函数 而不是我们想要的内存函数的执行结果
for (var i = 0; i < 5; i++)
buttons[i].onclick = function()
console.log(i);
(i);
上面的代码会在控制台输出0,1,2,3,4,五 行
这是因为function()(i)这样子写就相当于直接运行了这个函数 不用等事件触发
for (var i = 0; i < 5; i++)
buttons[i].onclick = function(i)
console.log(i);
(i);
或
for (var i = 0; i < 5; i++)
buttons[i].onclick = function(x)
console.log(x);
(i);
发现结果同上 可以发现是i参数覆盖事件参数x变成i, 但是依旧不是事件触发的时候才执行
for (var i = 0; i < 5; i++)
buttons[i].onclick = function()
return function()
console.log(i);
(i);
理解js的垃圾回收机制对闭包有很大帮助, 记住一点js不会回收需要用到的东西 而闭包正式要使用大外部变量的东西,所以如果外部的变量没有被回收 那么你才有可能访问到你需要的值
这样子写闭包是不对的因为那个console中的i不是(i)因为根本就没有产生关系,是因为内存函数根本就没有接收到你传的参数i,所以console的i会自动向上层查找i变量,因为是事件触发异步的所以此时的i都是5 正确的写应该是这样子的 如下
for (var i = 0; i < 5; i++)
buttons[i].onclick = function(i)
return function()
console.log(i);
(i);
或
for (var i = 0; i < 5; i++)
buttons[i].onclick = function(x)
return function()
console.log(x);
(i);
这样子写就能保证i在往上寻找时,找到的是你用外部i赋给i变量的值
这里那么多的内容是帮助理解闭包的工作原理 只是加深对js的理解,从以上的例子可以看出, 这种事件触发 并不是说直接最后执行,而是按照顺序执行, 只是你不按闭包来写 就感觉是最后才运行 其实依旧是顺序的执行 只不过是异步的触发 注意闭包外层的那里的(i)加上,如果没有当你触发的时候就是返回内层函数,而我们希望的是要执行内层函数,更进一步 你可以看到内层的x其实是新建的变量存储i变量的值,并不是i变量 根据js垃圾回收机制,你能发现x是不会被回收的,也就是实际上有五个x变量
如果你不用闭包,那么你就只能使用到最后一个i变量其值是5,这也就是常见的循环中放事件的结果不和你的料想一致的原因
接着 我们再来看 为什么那里的ajax为异步的调用 首先明确一点在异步模式中没有return这种说法,并且都是采用回调函数callback处理异步 这两点很关键 , 不注意这两点 可能你就会掉到坑里
function connectServer(callback)
if (window.XMLHttpRequest)
xmlhttp = new XMLHttpRequest();
else if (window.ActiveXObject)
xmlHttp = new ActiveXObject("Microsoft.XMLHttp");
else return;
xmlhttp.onreadystatechange = function()
if (xmlhttp.readyState == 4 && xmlhttp.status == 200)
callback(xmlhttp.responseText);
// 这里是异步调用的模式
// 这里的server是用node启动的服务端脚本,返回一个随机数
xmlhttp.open('GET', '../server', true);
xmlhttp.send();
buttons[i].onclick = function(i)
return function()
if (this.disabled) return;
bannedButtons(this, buttons);
this.childNodes[1].innerHTML = '...';
this.childNodes[1].style.visibility = 'visible';
connectServer(function(data)
buttons[i].childNodes[1].innerHTML = data;
bannedButtons(null, buttons);
enableButtons(buttons);
checkInfoIsReady(buttons);
);
(i);
分析如下
当用户触发button的点击事件时, 触发connectServer ()函数的执行这里首先是把一个匿名函数穿给callback这个参数,然后穿件一个XMLHttpRequest 对象,使用get方式异步的向服务器这里即是server脚本请求数据,接着这里的onreadystatechange会仍入一个队列(这个队列是专门来对异步程序存储的) 当轮到异步队列进行时这个函数得到执行, 也就是说如果你的程序有一个普通的死循环程序, 那么你不可能得到触发的结果, 因为普通代码的处理总是在异步队列的前面, 当服务端处理完成请求ok且可以响应了 然后执行里面的callback函数,刚才已经说了callback被函数赋值,而这里的data数据得到的就是服务端返回的数据, 接着就是对这个数据进行处理了, 这样就解决了异步调度的问题,因为后面的代码是依赖服务端返回的数据的,刚好这种回调函数的方法,解决了异步的问题
综上
再感悟下, 就是事件触发处理异步,也就是把利用垃圾回收机制,让所需要的变量不被回收,或者覆盖,从而实现,触发的时候是你所期望的值
再感悟下, 就是回调函数处理异步,也就是把要处理的东西,带到异步队列的感觉, 就是把要处理的东西,放到只有处理完才会进行的后面, 一般带延迟的东西,都是会抛到异步队列的, 所以你的代码也要放在异步中,防止再还没来得及得到数据时,先行处理完了
以上是关于js与ajax中异步调用的简单理解的主要内容,如果未能解决你的问题,请参考以下文章