⑴ js异步问题怎么解决
异步加载又叫非阻塞加载,浏览器在下载执行js的同时,还会继续进行后续页面的处理。主要有三种方式。
方法一:也叫Script DOM Element
(function(){
var scriptEle = document.createElement("script");
scriptEle.type = "text/javasctipt";
scriptEle.async = true;
scriptEle.src = "http://cdn.bootcss.com/jquery/3.0.0-beta1/jquery.min.js";
var x = document.getElementsByTagName("head")[0];
x.insertBefore(scriptEle, x.firstChild);
})();
<async>属性是HTML5中新增的异步支持。此方法被称为Script DOM Element 方法。Google Analytics 和 Google+ Badge 都使用了这种异步加载代码
(function(){;
var ga = document.createElement('script');
ga.type = 'text/javascript';
ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0];
s.parentNode.insertBefore(ga, s);
})();
但是这种加载方式执行完之前会阻止onload事件的触发,而现在很多页面的代码都在onload时还执行额外的渲染工作,所以还是会阻塞部分页面的初始化处理。
方法二:onload时的异步加载
(function(){
if(window.attachEvent){
window.attachEvent("load", asyncLoad);
}else{
window.addEventListener("load", asyncLoad);
}
var asyncLoad = function(){
var ga = document.createElement('script');
ga.type = 'text/javascript';
ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0];
s.parentNode.insertBefore(ga, s);
}
)();
这种方法只是把插入script的方法放在一个函数里面,然后放在window的onload方法里面执行,这样就解决了阻塞onload事件触发的问题。
注:DOMContentLoaded与load的区别。前者是在document已经解析完成,页面中的dom元素可用,但是页面中的图片,视频,音频等资源未加载完,作用同jQuery中的ready事件;后者的区别在于页面所有资源全部加载完毕。
方法三:其他方法
由于JavaScript的动态性,还有很多异步加载方法: XHR Injection、 XHR Eval、 Script In Iframe、 Script defer属性、 document.write(script tag)。
XHR Injection(XHR 注入):通过XMLHttpRequest来获取javascript,然后创建一个script元素插入到DOM结构中。ajax请求成功后设置script.text为请求成功后返回的responseText。
//获取XMLHttpRequest对象,考虑兼容性。
var getXmlHttp = function(){
var obj;
if (window.XMLHttpRequest)
obj = new XMLHttpRequest();
else
obj = new ActiveXObject("Microsoft.XMLHTTP");
return obj;
};
//采用Http请求get方式;open()方法的第三个参数表示采用异步(true)还是同步(false)处理
var xmlHttp = getXmlHttp();
xmlHttp.open("GET", "http://cdn.bootcss.com/jquery/3.0.0-beta1/jquery.min.js", true);
xmlHttp.send();
xmlHttp.onreadystatechange = function(){
if (xmlHttp.readyState == 4 && xmlHttp.status == 200){
var script = document.createElement("script");
script.text = xmlHttp.responseText;
document.getElementsByTagName("head")[0].appendChild(script);
}
}
XHR Eval:与XHR Injection对responseText的执行方式不同,直接把responseText放在eval()函数里面执行。
//获取XMLHttpRequest对象,考虑兼容性。
var getXmlHttp = function(){
var obj;
if (window.XMLHttpRequest)
obj = new XMLHttpRequest();
else
obj = new ActiveXObject("Microsoft.XMLHTTP");
return obj;
};
//采用Http请求get方式;open()方法的第三个参数表示采用异步(true)还是同步(false)处理
var xmlHttp = getXmlHttp();
xmlHttp.open("GET", "http://cdn.bootcss.com/jquery/3.0.0-beta1/jquery.min.js", true);
xmlHttp.send();
xmlHttp.onreadystatechange = function(){
if (xmlHttp.readyState == 4 && xmlHttp.status == 200){
eval(xmlHttp.responseText);
//alert($);//可以弹出$,表明JS已经加载进来。click事件放在其它出会出问题,应该是还没加载进来
$("#btn1").click(function(){
alert($(this).text());
});
}
}
Script In Irame:在父窗口插入一个iframe元素,然后再iframe中执行加载JS的操作。
var insertJS = function(){alert(2)};
var iframe = document.createElement("iframe");
document.body.appendChild(iframe);
var doc = iframe.contentWindow.document;//获取iframe中的window要用contentWindow属性。
doc.open();
doc.write("<script>var insertJS = function(){};<\/script><body onload='insertJS()'></body>");
doc.close();
GMail Mobile:业内JS内容被注释,所以不会执行,在需要的时候,获取script中的text内容去掉注释,调用eval()执行。
<script type="text/javascript">
/*
var ...
*/
</script>
HTML5新属性:async和defer属性
defer属性:IE4.0就出现。defer属声明脚本中将不会有document.write和dom修改。浏览器会并行下载其他有defer属性的script。而不会阻塞页面后续处理。注:所有的defer脚本必须保证按顺序执行的。
<script type="text/javascript" defer></script>
async属性:HTML5新属性。脚本将在下载后尽快执行,作用同defer,但是不能保证脚本按顺序执行。他们将在onload事件之前完成。
<script type="text/javascript" defer></script>
Firefox 3.6、Opera 10.5、IE 9和最新的Chrome和Safari都支持async属性。可以同时使用async和defer,这样IE 4之后的所有IE都支持异步加载。
没有async属性,script将立即获取(下载)并执行,期间阻塞了浏览器的后续处理。如果有async属性,那么script将被异步下载并执行,同时浏览器继续后续的处理。
总结: 对于支持HTML5的浏览器,实现JS的异步加载只需要在script元素中加上async属性,为了兼容老版本的IE还需加上defer属性;对于不支持HTML5的浏览器(IE可以用defer实现),可以采用以上几种方法实现。原理基本上都是向DOM中写入script或者通过eval函数执行JS代码,你可以把它放在匿名函数中执行,也可以在onload中执行,也可以通过XHR注入实现,也可以创建一个iframe元素,然后在iframe中执行插入JS代码。
⑵ js单线程和js异步操作的几种方法
为了解决这个问题,Javascript语言将任务的执行模式分成两种:同步(Synchronous)和异步(Asynchronous)。
"同步模式"就是上一段的模式,后一个任务等待前一个任务结束,然后再执行,程序的执行顺序与任务的排列顺序是一致的、同步的;"异步模式"则完全不同,每一个任务有一个或多个回调函数(callback),前一个任务结束后,不是执行后一个任务,而是执行回调函数,后一个任务则是不等前一个任务结束就执行,所以程序的执行顺序与任务的排列顺序是不一致的、异步的。
"异步模式"非常重要。在浏览器端,耗时很长的操作都应该异步执行,避免浏览器失去响应,最好的例子就是Ajax操作。在服务器端,"异步模式"甚至是唯一的模式,因为执行环境是单线程的,如果允许同步执行所有http请求,服务器性能会急剧下降,很快就会失去响应。
⑶ 如何进行nodejs异步编程
更新下,我之所以让您玩一下AJAX,是希望您体验一下异步,并不是希望您了解AJAX这机制的实现方法,因为AJAX是一个特别典型且简单的异步场景,比如:
执
行某个函数 -> 执行语句A,B,C,D -> 在D语句发起异步请求,同时向引擎注册一个回调事件 -> 执行E,F,G
->退出函数块 ,引擎Loop...Loop...Loop,此时异步的请求得到了Response,之前注册的回调被执行。
@VILIC VANE
也提到了,实际上Node.js主要是为了应对主流web
app存在大量I/O等待而CPU闲置的场景所衍生的解决方案,而在架构上,它的后端有一个底层的worker封装,每当你有一个诸如addUser这样
的I/O操作时,它们都会被交由worker去执行从而达到让出尽快让出当前函数的执行权的目的,在向引擎注册完回调后,内部会通过事件轮询去检查该I
/O事件的句柄,当句柄显示该事件操作完成后,则注册的回调则被执行。
所以,假设有人(按题设,简化一下场景,有且只有2个人)同时请求
addUser(A)和userList(B),B的请求会在执行完A的请求内部所有同步代码后被执行,而哪怕worker此时仍然在进行addUser
这一 I/O操作,用户B也并不会被引擎挂起或者等待。这就是为什么Node.js单节点却一样可以拥有高负载能力的原因。
至于什么样的代码是异步的,你看看node文档里fs模块的使用方法就知道了,大概的形式就是如下这种。
mole.method( args [,callback] )
当然还有一种比较极端的情况,假设您使用的数据库是山寨的,驱动是基于同步实现的,那么B就该等多久等多久把,树荫底下喝杯茶,下个棋,和后面的C,D,E,F,G打个招呼呗~
我推荐您先去玩一下前端的AJAX了解一下 异步编程方式,体验一下异步的“感觉”,然后看一本叫《JavaScript异步编程》的书。
Node.js
是一款基于Event-driven的模型构建的Framework,它典型的特征就是通过内置的事件轮询来调度事件,通常来说node.js的数据库驱
动都是基于异步实现的,所以在实际情况中,A提交博客和B注册用户这两个请求是可以同时由Node.js
来handle,并按照实际操作的处理事件分别调度给予浏览器响应。
当然,假设您在业务代码里写了一个耗时很久的同步代码(比如直接写一
个while(true)的loop,Node就死了),由于JavaScript本身单线程的限制,所以整个App就会被block住,后续的事件/程
序只有等到该段代码执行完成之后才会被处理,这也是为什么我们通常不建议在Node.js层做大规模计算(JS本身的计算效率太低,会导致Node吞吐量
会大大降低),而倾向由C++的拓展去实现。
⑷ > 如何将JS代码更换成异步统计代码
网站统计异步代码以异步加载形式加载网站分析代码,使用该代码可以大幅提升网站的响应速度。
注意:使用异步代码不提供显示统计图标。
如何更新部署异步统计代码?
第一步:找到原js代码,比如如下:
<scriptsrc='http://w.cnzz.com/c.php?id=XXXXXXXX&l=2'language='JavaScript'charset='gb2312'></script>
第二步:把原代码替换成如下片段,然后上传服务器:
<script>
varcnzz_s_tag=document.createElement('script');
cnzz_s_tag.type='text/javascript';
cnzz_s_tag.async=true;
cnzz_s_tag.charset=“utf-8”;
cnzz_s_tag.src=“http://w.cnzz.com/c.php?id=XXXXXXXX&async=1”;
varroot_s=document.getElementsByTagName('script')[0];
root_s.parentNode.insertBefore(cnzz_s_tag,root_s);
</script>
添加好异步统计代码之后,一定要删除原来默认统计代码,否则统计数据会重复计算。
注:若是https的网站,把上面代码里的http改成https即可
⑸ javascript同步和异步的区别与实现方式
举个生活中的示例就会很明白:
如:
早上起床,先刷牙,再烧水,等水烧开了洗脸,再整理发型.是同步
先刷牙,再烧水,再整理发型,等水壶滴的一声通知我水烧开了,我再取刚烧开的水洗脸,是异步.
<script>
varflag=false;
functionfuncTest(t,func){
setTimeout(function(){
(function(param){
console.log(param);
func();
}(t));
},t*1000);
}
varfuncList=[];
funcList.push(function(){funcTest(4,function(){
flag=true;//同步标记量
})});//不同的异步函数添加进队列
funcList.push(function(){funcTest(3,function(){
flag=true;
})});//不同的异步函数添加进队列
funcList.push(function(){funcTest(2,function(){
flag=true;
})});//不同的异步函数添加进队列
dealFuncSync(funcList);
functiondealFuncSync(funcList){
functioncallBackSync(){
if(!funcList||funcList.length==0){
console.log('end');
return;
}
flag=false;
funcList.shift()();
setTimeout(function(){
if(flag){//控制队列函数同步
callBackSync();
}else{
setTimeout(arguments.callee,100);
}
},100);
}
callBackSync();
}
</script>
⑹ 如何优雅地写 JS 异步循环
用yield
示例如下:
//异步函数
function*a(param){
console.log(param)
}
//循环
vartask=[]
for(vari=0;i<10;i++){
task.push(a(i))
}
//执行
varhandles=yieldtask
console.log(handles)
⑺ nodejs 异步应该如何处理
结果当然是空数组因为异步,会先执行console.log(),要想得到只能把console.log()写在内回调函数容里。回调函数是当函数执行结束后才会调用的。
var fileArr = [];
//读取文件目录
fs.readdir(lastest_pages_path,function(err,files){
if(err){
console.log(err);
return;
}
fileArr.push(files);
console.log(fileArr);
}
⑻ js如何异步执行方法
functionmyThread(callback){
returnsetTimeout(1000*10,function(){
$("#div").append("<p>hello</p>");//10秒后在div中加一个行,然后在执行callback函数
callback();
});
}
用回调内函容数
functionA(fun){
vartemp=100;
temp=temp*temp;
window.setTimeout(function(){
fun(temp);
},0);
alert("a函数:"+temp);
}
functionB(r){
alert("b函数"+r);
}
A(B);//调用