NodeJS如何实现同步的方法示例
前言
众所周知,异步是得天独厚的特点和优势,但同时在程序中同步的需求(比如控制程序的执行顺序为:func1->func2->func3)也是很常见的。
下面这篇文章主要介绍了关于NodeJS实现同步的相关内容,NodeJS被打上了单线程、非阻塞、事件驱动…..等标签。在单线程的情况下,是无法开启子线程的。经过了很久的研究,发现并没有thread函数!!!但是有时候,我们确实需要“多线程”处理事务。nodeJS有两个很基础的api:setTimeout和setInterval。这两个函数都能实现“异步”。nodeJS的异步实现:nodeJS有一个任务队列,在使用setInterval函数的时候,会每隔特定的时间向该任务队列增加任务,从而实现“多任务”处理。但是,“特定的时间”不代表是具体的时间,也有可能是会大于我们设定的时间,也有可能小于。
我们跑跑下面代码块
setInterval(function(){ console.log(newDate().getTime()); },1000);
输出的结果如下:
1490531390640
1490531391654
1490531392660
1490531393665
1490531394670
1490531395670
1490531396672
1490531397675
......
我们可以看到,所有的时间间隔都是不一样的。时间的偏移不仅包含了间隔的1s,还包含了console.log()的耗时,以及newDate()的耗时。在大量的数据统计下,时间间隔近似于1s。
问题来了,setInterval是能实现多任务的效果,但是怎样才能实现任务之间的同步操作呢?
这里实现的方法是通过回调函数实现的。
functiona(callback){ //模拟任务a耗时 setTimeout(function(){ console.log("taskaend!"); //回调任务b callback(); },3000); }; functionb(){ setTimeout(function(){ console.log("taskbend!"); },5000); } a(b);
这里举了一个很简单的例子,就是将b方法的实现赋值给a方法的callback函数从而实现函数回调,但是会有个问题。假设a方法依赖于b方法,b方法依赖于c方法,c方法依赖于d方法…..也就意味着每个方法的实现都需要持有上一个方法的实例,从而实现回调。
functiona(b,c,d){ console.log("helloa"); b(c,d); }; functionb(c,d){ console.log("hellob"); c(d); }; functionc(d){ console.log("helloc"); d() }; functiond(){ console.log("hellod"); }; a(b,c,d);
输出结果
helloa
hellob
helloc
hellod
如果回调函数写的多了,会造成代码特别特别恶心。
如果有类似于sync的函数能让任务顺序执行就更好了。终于找到了async这个库$npminstanllasync
async=require("async"); a=function(callback){ //延迟5s模拟耗时操作 setTimeout(function(){ console.log("helloworlda"); //回调给下一个函数 callback(null,"functiona"); },5000); }; b=function(callback){ //延迟1s模拟耗时操作 setTimeout(function(){ console.log("helloworldb"); //回调给下一个函数 callback(null,"functionb"); },1000); }; c=function(callback){ console.log("helloworldc"); //回调给下一个函数 callback(null,"functionc"); }; //根据b,a,c这样的顺序执行 async.series([b,a,c],function(error,result){ console.log(result); });
注释基本能够很好的理解了,我们看看输出
helloworldb
helloworlda
helloworldc
['functionb','functiona','functionc']
上面的基本async模块的实现的如果了解更多关于async模块的使用,可以点击:查看详情
其实nodeJS基本api也提供了异步实现同步的方式。基于Promise+then的实现
sleep=function(time){ returnnewPromise(function(){ setTimeout(function(){ console.log("end!"); },time); }); }; console.log(sleep(3000));
输出结果为:
Promise{
}
end!
可以看出来,这里返回了Promise对象,直接输出Promise对象的时候,会输出该对象的状态,只有三种:PENDING、FULFILLED、REJECTED。字面意思很好理解。也就是说Promise有可能能实现我们异步任务同步执行的功能。我们先用Promise+then结合起来实现异步任务同步操作。
sleep=function(){ returnnewPromise(function(resolve,reject){ setTimeout(function(){ console.log("start!"); resolve(); },1000); }) .then(function(){ setTimeout(function(){ console.log("end!"); },2000); }) .then(function(){ console.log("end!!"); }) }; console.log(sleep(1000));
输出结果:
Promise{
}
start!
end!!
end!
在newPromise任务执行完后,调用了resolve才会执行所有的then函数,并且这些then函数是异步执行的。由输出结果可以知道。(如果所有then是顺序执行的应该是end!->end!!)。但是上述也做到了两个异步任务之间顺序执行了。
不过,还有更加优雅的方式:使用async+await。
display=function(time,string){ returnnewPromise(function(resovle,reject){ setTimeout(function(){ console.log(string); resovle(); },time) }); }; //执行顺序:bac fn=asyncfunction(){ //会造成阻塞 awaitdisplay(5000,"b"); awaitdisplay(3000,"a"); awaitdisplay(5000,"c"); }();
输出结果:
b
a
c
由于这里时间输出比较尴尬,只能通过我们来感知,本人通过个人“感知”知道了在displayb过度到displaya的时候大概用了3s,再过度到displayc的时候大概用了5s
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对毛票票的支持。
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。