JS异步编程

38 篇文章 1 订阅
知识线

JS 为什么是单线程? => 单线程带来的问题?=> 如何实现异步编程?(同步和异步) =>异步代码的执行顺序 => EventLoop运行机制。


JS 为什么是单线程?

JS 单线程的特点就是同一时刻只能执行一个任务。

这是由一些与用户的互动以及操作 DOM 等相关的操作决定了 JS 要使用单线程,否则使用多线程会带来 复杂的同步问题。如果是多线程,一个线程正在修改 DOM,另一个线程正在删除 DOM,那么以哪一 个为准呢?

如果执行同步问题的话,多线程需要加锁,执行任务造成非常的繁琐

注意:HTML5标准规定,允许 JavaScript 脚本创建多个线程,但是子线程完全受主线程控制,且不得操作 DOM 。

单线程带来的问题?

由于 JavaScript 是单线程的,单线程就意味着阻塞问题,当一个任务执行完成之后才能执行下一个任务。这样就会导致出现页面卡死的状态,页面无响应,影响用户的体验,所以不得不出现了同步任务和异步任务的解决方案。

  • 同步任务: 在主线程上排队执行的任务,只有前一个任务执行完毕,才能执行后一个任务。
  • 异步任务: 不进入主线程、而进入"任务队列"的任务,只有"任务队列"通知主线程,某个异步任务可以执行了,该任务才会进入主线程执行。
如何实现异步编程?

为了解决上述问题,出现了异步任务执行,它的运行机制如下:

  • 所有同步任务都在主线程上执行,形成一个执行栈
  • 主线程之外,还存在一个"任务队列"。只要异步任务有了运行结果,就在"任务队列"之中放置一个 事件。
  • 一旦"执行栈"中的所有同步任务执行完毕,系统就会读取"任务队列",看看里面有哪些事件。那些 对应的异步任务,于是结束等待状态,进入执行栈,开始执行。
  • 主线程不断重复上面的第三步

注意:在主线程读取任务队列的时候,任务队列是一种“先进先出”的数据结构,排在前面的事 件,优先被主线程读取。执行栈只要执行空,任务队列的第一个事件进入主线程。同时,如果存 在定时器,主线程需要检查定时器执行的时间,到了时间才能给主线程执行。

面试官:JS 如何实现异步编程?

回调函数

回调函数就是作为异步任务的执行。异步任务必须指定回调函数。

回调函数不是直接调用,而是在特定的事件或条件发生时另一方调用的,用于对该事件或条件进行响 应。比如 Ajax 回调:

// jQuery 中的 ajax
$.ajax({
	type : "post",
	url : 'test.json',
	dataType : 'json',
	success : function(res) {
		// 响应成功回调
	},
	fail: function(err){
		// 响应失败回调
	}
});


但是如果某个请求存在依赖性,如下:

 $.ajax({
    type: "post",
    success: function (res) {//成功回调
      //再次异步请求
      $.ajax({
        type: "post",
        url: "...?id=res.id,
	    	success: function (res) {
          $.ajax({
            type: "post",
            url: "...?id=res.id,
            success: function () {
              // 往复循环

            }
          })
        }
      })
    }
  })

就会形成不断的循环嵌套,我们称之为回调地狱。我们可以看出回调地狱有以下缺点:

  • 嵌套函数存在耦合性,一旦有所改动,牵一发而动全身。
  • 嵌套函数一多,就很难处理错误。
  • 回调函数不能使用 try catch捕获异常(异常的捕获只能在函数执行的时候才能捕获到)。
  • 回调函数不能直接return
为什么不能捕获异常?

其实这跟 js 的运行机制相关,异步任务执行完成会加入任务队列,当执行栈中没有可执行任务了,主 线程取出任务队列中的异步任务并入栈执行,当异步任务执行的时候,捕获异常的函数已经在执行栈内 退出了,所以异常无法被捕获。

为什么不能 return?

return只能终止回调的函数的执行,而不能终止外部代码的执行。

解决回调地狱问题

面试官:如何解决回调地狱问题呢?

可以参考 promise详解–传送门es6笔记之promise–传送门

Event Loop

详见 EventLoop详解–传送门

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

°PJ想做前端攻城狮

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

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

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

打赏作者

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

抵扣说明:

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

余额充值