JavaScript中异步编程的工作模式 --- 同步模式/异步模式||异步的EventLoop消息队列

Part01 --- 概述

JavaScript是以单线程为主的工作模式

采用单线程工作的原因

        最早JavaScript在设计的初衷是在浏览器中解决交互问题的脚本语言,以操作浏览器dom元素为主。

        如果同时在浏览器中添加一条dom,并且在下一行代码中删除了一条dom,在多线程的环境下浏览器并不能确认具体以那一条代码为基准进行执行。因此,将JavaScrtpt设计为单线程,也就是逐行执行。

        这样的优势也就是更安全,并且因为逐行执行也更简单便于阅读。

        但是弊端也很明显,如果有一条非常耗时的操作,他会阻塞代码执行,直到操作结束,因此下面的代码必须等待耗时操作结束,因此对性能会有较大的影响。

所以JavaScript为了解决耗时任务的执行,将执行模式分成了两种:同步模式/异步模式


Part 02 --- 同步模式

同步模式(SyncHronous)

        同步模式指的就是我们代码当中的任务依次执行,后一个任务也就必须等待前一个代码接受才能开始执行。

        程序的执行顺序与我们代码的编写顺序是完全一致的。

举例同步模式执行:

console.log('global begin');

function bar() {
    console.log('bar task');
}

function foo() {
    console.log('foo task');
    bar()
}

foo()

console.log('global end');

调用栈顺序

call stack

(anonymous) // 匿名调用  可以理解为将所有的代码压入一个匿名函数中进行调用

console.log('global begin'); // 压入调用栈  调用结束释放

foo()  // 压入调用栈

console.log('foo task'); // 调用 foo函数中的console.log   调用结束释放

bar()   //  将foo函数中的bar函数压入调用栈

console.log('bar task'); // 调用 bar函数中的console.log  调用结束释放

// 结束 bar 调用

// 结束 foo 调用


console.log('global end'); // 压入调用栈  调用结束释放

// 代码结束执行

 


Part 03 --- 异步模式

异步模式(AsyncHronous)

        异步模式的api,不会等待这个任务的结束,才开始下一个任务。

        对于耗时的任务,他都是开启过后立即往后执行下一个任务。

        后续逻辑一般会通过回调函数的方式去定义。

如果没有异步模式,单线程的JavaScript就无法同时处理大量的耗时任务。

举例异步模式执行:

console.log('global begin');

setTimeout(function time1() {
    console.log('time1 invoke');
}, 1800)

setTimeout(function time2() {
    console.log('time2 invoke');
    setTimeout(() => {
        console.log('inner invoke');
    }, 1000);
}, 1000)

console.log('golbal end');

Call stack

console.log('global begin');  // 压栈 释放

time1 .//  异步模式  调用挂起

time2  //  异步模式  调用挂起

console.log('golbal end');  //  压栈  释放

console.log('time2 invoke'); // time2调用 

inner //  异步模式 调用挂起

//time2 调用结束释放

console.log('time2 invoke'); // time1调用   

// time1 调用结束 释放

console.log('inner invoke');  // inner 调用

// inner 调用结束 释放

Web APIs

time1  1.8s

time2 1s

inner 1s

Event loop

time2  // 倒计时先结束 进入事件队列 排队  再放入调用栈 

time1 //  倒计时结束  进入队列排队

inner //  倒计时结束 进入队列排队

        直到消息队列EventLoop和调用栈 都执行结束了,那么代码才会释放调用栈中的匿名函数

        如果,我们把调用栈看作为执行的工作表,那么我们可以把EventLoop可以称之为代办的工作表。当调用栈执行结束后才会依次执行消息队列中的调用

        整个过程中可以不断地向消息队列中放入任务,那这些任务中会根据在异步结束后的顺序,在消息队列中进行排队等待执行。

 


Part 04 --- 回调函数

回调函数(call back)

所有异步编程方案的根基

// 定义异步函数
function foo(callback) {
    setTimeout(() => {
        callback()
    }, 3000);
}

// 执行异步函数
foo(function() {
    console.log(('这就是一个回调函数'));
    console.log(('调用者定义这个函数,执行者执行这个函数'));
    console.log(('其实就是调用者告诉异步任务结束后应该做什么'));
})

由调用者定义,交给执行者执行的函数称之为回调函数。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值