欢迎您访问 最编程 本站为您分享编程语言代码,编程技术文章!
您现在的位置是: 首页

JavaScript是怎样实现异步操作的原理?

最编程 2024-07-26 06:55:49
...

我们知道javascript是单线程的,但是为什么有很多的事件处理却是异步的呢?
javascript的单线程的意思是,只有一个主线程来解释执行javascript代码。

那么javascript是如何实现异步的呢?

异步过程

首先,主线程发起一个异步请求,相应的工作线程就接收这个请求并进行处理,期间,主线程发完请求之后就去干别的事情去了。等到工作线程的处理有了结果,浏览器内部就分配一个线程出来,通知主线程,刚刚发起的异步请求有了结果(这个通知过程其实是将回调函数推入消息队列中,也叫事件队列,也叫任务队列),等到主线程处理完了当前调用栈中的任务,就会从这个消息队列中读取消息,也就是调用回调。这样就完成了一次读取消息的循环。

而javascript执行代码的机制就是不断地从消息队列中读取消息回调并执行的过程。因为每条消息(或者说每个回调)都是由相应的事件(比如鼠标点击,ajax,定时器事件等)触发的,所以这个过程称之为事件循环。


image.png

在上面把消息推送到事件队列的这个过程中,如果工作线程处理的任务既有宏任务,也有微任务,则优先处理宏任务,然后把对应宏任务的消息推送到宏任务消息队列中;然后工作线程再处理微任务,接着把对应微任务的消息推送到微任务的消息队列中。
注意,宏任务消息队列与微任务消息队列不是同一个队列
当主线程处理完当前调用栈中的任务后,优先从微任务消息队列中读取消息,也就是先执行微任务的回调,等到微任务的消息队列为空,再去读取宏任务的消息队列。

注意区分推送顺序和读取顺序。

由此,js中的任务分为同步任务和异步任务

  • 同步任务是指:当前主线程将要消化执行的任务,这些任务一起形成执行栈(execution context stack)。
  • 异步任务是指:不进入主线程,而是进入任务队列(task queque),即不会马上进行的任务。

使用异步的方法

  • 回调
  • Promise
  • generator
  • async/await

举例
红绿灯交替变亮,红灯3s亮一次,绿灯1s亮一次,黄灯2s亮一次

// 红绿灯,红灯3s亮一次,绿灯1s亮一次,黄灯2s亮一次,并交替展示
function red() {console.log('红灯亮')}
function green() {console.log('绿灯亮')}
function yellow() {console.log('黄灯亮')}
// 回调
// var step = (timer, light, callback) => {
//   var timer1 = setTimeout(() => {
//     if(light === 'red') {
//       red()
//     }
//     if(light === 'green') {
//       green()
//     }
//     if(light === 'yellow') {
//       yellow()
//     }
//     callback()
//   },timer)
// }
// 回调
// var task = () => {
//   step(3000,'red', () => {
//     step(1000,'green',() => {
//       step(2000, 'yellow', task)
//     })
//   })
// }
// task();

// Promise
var step = (timer,light) => {
  return new Promise((resolve,reject) => {
    var timer2 = setTimeout(() => {
      if(light === 'red') {
        red()
      }
      if(light === 'green') {
        green()
      }
      if(light === 'yellow') {
        yellow()
      }
      resolve()
    },timer)
  })
}
// // Promise
// var task = () => {
//   step(3000,'red').then(() => {
//     step(1000,'green').then(() => {
//       step(2000,'yellow').then(task)
//     })
//   })
// }
// task();

//async/await
// var task = async() => {
//   await step(3000,'red')
//   await step(1000,'green')
//   await step(2000,'yellow')
//   task()
// }
// task()

// generator
function *task() {
  yield step(3000,'red');
  yield step(1000,'green');
  yield step(2000,'yellow');
}
var gen = task()

推荐阅读