[JavaScript学习记录] 异步操作

JavaScript 引擎有多个线程,单个脚本只能在主线程运行,其他线程都在后台配合.

单线程模型虽然对 JavaScript 构成了很大的限制,但也因此使它具备了其他语言不具备的优势。如果用得好,JavaScript 程序是不会出现堵塞的,这就是为什么 Node 可以用很少的资源,应付大流量访问的原因。


目录

 一.定时器

setTimeout(JavaScript函数/要执行的代码, 等待的毫秒数)

clearTimeout(timeoutID)

setInterval(JavaScript函数/要执行的代码, 等待的毫秒数)

二.几种模式

1.回调函数

2.事件监听

3.发布/订阅

三.流程控制

1.串行执行(一个任务完成以后,再执行另一个)

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();

 (两个两个进行)

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

泥烟

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值