[JavaScript学习记录] 异步操作
JavaScript 引擎有多个线程,单个脚本只能在主线程运行,其他线程都在后台配合.
单线程模型虽然对 JavaScript 构成了很大的限制,但也因此使它具备了其他语言不具备的优势。如果用得好,JavaScript 程序是不会出现堵塞的,这就是为什么 Node 可以用很少的资源,应付大流量访问的原因。
目录
setTimeout(JavaScript函数/要执行的代码, 等待的毫秒数)
setInterval(JavaScript函数/要执行的代码, 等待的毫秒数)
2.并行执行(所有异步任务同时执行,等到全部完成以后,才执行)
3.串并结合(设置一个门槛,每次最多只能并行执行n个异步任务)
一.定时器
setTimeout(JavaScript函数/要执行的代码, 等待的毫秒数)
(三秒后会出现一个"ABC"的按钮)
<p id="content"> 请等三秒钟!</p>
<script>
setTimeout("changeState()",3000 );
function changeState(){
var content=document.getElementById('content');
content.innerHTML="<input type='button' value='ABC'>";
}
</script>
(一个计时器)
<input type="button" id="displayBox" value="0">
<script>
x = 0
function countSecond()
{
x = x+1
document.getElementById("displayBox").value=x
setTimeout("countSecond()", 1000)
}
countSecond()
</script>
clearTimeout(timeoutID)
timeoutID 为调用 setTimeout() 函数时所获得的返回值,使用该返回标识符作为参数,可以取消该 setTimeout() 所设定的定时执行操作
<form class="countNum">
<input type="text" id="addNum" value="0" size="4" >
<input type="button" value="开始" onclick="countNum()">
<input type="button" value="停止" onclick="clearTimeout(matter)">
</form>
<script>
x = 0
function countNum(){
document.getElementById('addNum').value=x;
x += 1
matter=setTimeout("countNum()",1000)
}
function stopNum(){
}
</script>
setInterval(JavaScript函数/要执行的代码, 等待的毫秒数)
一个时钟
<p id="timer"></p>
<script>
setInterval("myTimer()",1000)
function myTimer(){
var d=new Date();
var t=d.toLocaleTimeString();
document.getElementById('timer').innerHTML = t
}
</script>
二.几种模式
1.回调函数
优点 | 缺点 |
简单、容易理解和实现 | 各个部分之间高度耦合,使得程序结构混乱、流程难以追踪(尤其是多个回调函数嵌套的情况),而且每个任务只能指定一个回调函数 |
function f1(callback) {
// ...
callback();
}
function f2() {
// ...
}
f1(f2);
2.事件监听
优点 | 缺点 |
容易理解,,有利于实现模块化 | 整个程序都要变成事件驱动型,运行流程会变得很不清晰, 难以分辨出主流程 |
f1.on('done', f2);
function f1() {
setTimeout(function () {
// ...
f1.trigger('done');
}, 1000);
}
f1.trigger('done')
表示,执行完成后,立即触发done
事件,从而开始执行f2
3.发布/订阅
与“事件监听”类似,但是优于后者。因为可以通过查看“消息中心”,了解存在多少信号、每个信号有多少订阅者,从而监控程序的运行 |
f2向信号中心jQuery订阅done信号
jQuery.subscribe('done', f2);
function f1() {
setTimeout(function () {
// ...
jQuery.publish('done');
}, 1000);
}
f1执行完成后,向信号中心jQuery发布done信号,从而引发f2
f2完成执行后,可以取消订阅
jQuery.unsubscribe('done', f2);
三.流程控制
1.串行执行(一个任务完成以后,再执行另一个)
在下面的例子,goals
数组表示每一个异步任务的参数,results
数组保存每一个异步任务的运行结果, Series
就是串行函数,它会依次执行异中步任务,所有任务都完成后,才会执行Final函数。
var goals = [1, 2, 3, 4, 5, 7];
var results = [];
function ShowStep(num, callback){
console.log('参数为 ' + num +' , 1秒后返回结果');
setTimeout(function(){ callback(num*2); }, 1000);
}
function Final(valueFinal){
console.log('完成, 最后的生成值为: ', valueFinal);
}
function Series(goal){
if(goal){
ShowStep(goal, function(result){
results.push(result);
return Series(goals.shift());
});
}else{
return Final(results[results.length-1]);
}
}
Series(goals.shift());
输出 :
2.并行执行(所有异步任务同时执行,等到全部完成以后,才执行)
var goals = [ 1, 2, 3, 4, 5, 7 ];
var results = [];
function ShowStep(num, callback) {
console.log('参数为 ' + num +' , 1秒后返回结果');
setTimeout(function () { callback(num * 2); }, 1000);
}
function Final(valueFinal) {
console.log('完成,最后的生成值为: ', valueFinal);
}
goals.forEach(function(item) {
ShowStep(item, function(result){
results.push(result);
if(results.length === goals.length) {
Final(results[results.length - 1]);
}
})
});
forEach
方法会同时发起六个异步任务,等到它们全部完成以后,才会执行Final函数 .
这次用时变为上面的六分之一(仅需一秒就能完成整个脚本),问题在于如果并行的任务较多,很容易耗尽系统资源,拖慢运行速度, 因此有了二者结合的流程控制方式👇👇👇
3.串并结合(设置一个门槛,每次最多只能并行执行n
个异步任务)
避免过分占用系统资源
var goals = [ 1, 2, 3, 4, 5, 7 ];
var results = [];
var running = 0;
var limit = 2;
function async(num, callback) {
console.log('参数为 ' + num +' , 1秒后返回结果');
setTimeout(function () { callback(num * 2); }, 1000);
}
function Final(valueFinal) {
console.log('完成:,最后的生成值为: ', valueFinal);
}
function launcher() {
while(running < limit && goals.length > 0) {
var item = goals.shift();
async(item, function(result) {
results.push(result);
running--;
if(goals.length > 0) {
launcher();
} else if(running == 0) {
Final(results);
}
});
running++;
}
}
launcher();
(两个两个进行)
本文来自博客园,作者:泥烟,CSDN同名, 转载请注明原文链接:https://www.cnblogs.com/Knight02/p/15799140.html