剖析异步

先看一段代码

function f2() {
    console.log(2)
}
function f1(callback){
    callback()
    console.log(1)
}
f1(f2)
//2 1 3
function f2() {
    console.log(2)
}
function f1(callback){
    setTimeout(callback,0)
    console.log(1)
}
f1(f2)
//1 3 2
  • 上面代码有何区别呢,第一段代码f1函数返回之前callback会被立即执行
    第二段代码则是f1函数返回之后要等任务完成之后才调用callback。
    这里的setTimeout将callback加入任务队列
  • 跟java中的异步和同步代码会交叉输出相比,js中的异步其实是排好队输出的。由于js是单线程执行代码的,所以没有那种交叉输出的效果。
  • setTimeout的回调的执行顺序不仅与代码顺序有关还和延迟时间有关。
f1();
f2();
f3();

如果f1中执行了大量的耗时操作,而且f2需要在f1之后执行。则程序可以改为回调的形式。如下:

function f1(callback){
    setTimeout(function () {
      // f1的大量耗时任务代码并的到三个结果i,l,you.
      console.log("this is function1");
      var i = "i", l = "love", y = "you";
        if (callback && typeof(callback) === "function") {
            callback(i,l,y);
        }
    }, 50);
}

function f2(a, b, c) {
    alert(a + " " + b + " " + c);
    console.log("this is function2");
}

function f3(){console.log("this is function3");}
f1(f2);
f3();

运行结果:

this is function3
this is function1
i love you
this is function2
  • 采用这种方式,我们把同步操作变成了异步操作,f1不会堵塞程序运行,相当于先执行程序的主要逻辑,将耗时的操作推迟执行。回调函数的优点是简单,轻量级(不需要额外的库)。缺点是各个部分之间高度耦合(Coupling),流程会很混乱,而且每个任务只能指定一个回调函数。某个操作需要经过多个非阻塞的IO操作,每一个结果都是通过回调,产生意大利面条式(spaghetti)的代码。
  • Promises的本质实际就是通过状态机来实现的
setTimeout(()=>console.log(4),0)
var p1=new Promise(function(resolve,reject){
    setTimeout(()=> console.log(3),0)
    resolve('hello')
}).then(function(val){
    console.log(val)
})
setTimeout(()=> console.log(2),0)
console.log(5)
//5 hello 4 3 2
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值