首页 > 编程语言 >JavaScript 中的异步任务、同步任务、宏任务与微任务

JavaScript 中的异步任务、同步任务、宏任务与微任务

时间:2024-09-14 23:49:45浏览次数:12  
标签:异步 同步 console log 队列 JavaScript 任务 执行

JavaScript 中的异步任务、同步任务、宏任务与微任务

在 JavaScript 的世界里,理解异步任务、同步任务、宏任务和微任务是非常重要的,它们共同构成了 JavaScript 独特的执行机制。

一、同步任务与异步任务

1. 同步任务

  • 定义:同步任务是在代码执行过程中,按照顺序依次执行的任务。每个同步任务必须等待前一个任务完成后才能开始执行。
  • 特点
    • 阻塞代码执行,直到任务完成。
    • 按照代码书写的顺序依次执行。
  • 示例
    console.log('同步任务 1');
    console.log('同步任务 2');
    
    在这个例子中,首先会输出“同步任务 1”,然后输出“同步任务 2”。这两个任务是按照顺序依次执行的,前一个任务完成后,后一个任务才会开始执行。

2. 异步任务

  • 定义:异步任务是在代码执行过程中,不会立即执行,而是在特定的时间或条件满足后才会执行的任务。异步任务不会阻塞代码的执行,允许其他任务在等待异步任务完成的过程中继续执行。
  • 特点
    • 不会阻塞代码执行,可以在后台执行。
    • 通常需要回调函数来处理结果。
  • 示例
    console.log('同步任务 1');
    setTimeout(() => {
        console.log('异步任务');
    }, 1000);
    console.log('同步任务 2');
    
    在这个例子中,首先会输出“同步任务 1”,然后输出“同步任务 2”。接着,由于setTimeout是一个异步任务,它会在 1000 毫秒后执行回调函数,输出“异步任务”。在等待异步任务执行的过程中,其他同步任务可以继续执行。

二、宏任务与微任务

1. 宏任务

  • 定义:宏任务是由浏览器或 Node.js 等环境提供的任务,通常包括setTimeoutsetIntervalAjax 请求DOM 事件等。宏任务会在主线程上依次执行,每个宏任务执行完毕后,会检查微任务队列是否为空,如果不为空,则执行微任务队列中的所有任务。
  • 特点
    • 执行时间相对较长。
    • 会导致页面的重新渲染。
  • 示例
    console.log('同步任务 1');
    setTimeout(() => {
        console.log('宏任务 1');
    }, 0);
    console.log('同步任务 2');
    
    在这个例子中,setTimeout中的回调函数是一个宏任务,会在同步任务执行完毕后被放入任务队列等待执行。即使设置的时间为 0,也不会立即执行,而是在同步任务执行完毕后,按照任务队列的顺序执行。

2. 微任务

  • 定义:微任务是在当前宏任务执行过程中产生的,并且会在当前宏任务执行完毕后立即执行。常见的微任务包括Promise.then()Promise.catch()Promise.finally()MutationObserver等。
  • 特点
    • 执行时间相对较短。
    • 优先级高于宏任务。
  • 示例
    console.log('同步任务 1');
    Promise.resolve().then(() => {
        console.log('微任务 1');
    });
    console.log('同步任务 2');
    
    在这个例子中,Promise.resolve().then()中的回调函数是一个微任务,会在同步任务执行完毕后,且在宏任务执行之前被执行。

三、事件循环

JavaScript 是单线程语言,通过事件循环来管理同步任务和异步任务的执行。事件循环的工作原理如下:

  1. 首先执行同步任务,将同步任务依次放入主线程执行。
  2. 当遇到异步任务时,将异步任务放入任务队列中等待执行。异步任务分为宏任务和微任务,分别放入不同的任务队列。
  3. 当主线程中的同步任务执行完毕后,会先检查微任务队列是否为空。如果微任务队列不为空,则执行微任务队列中的所有任务,这个过程会持续进行,直到微任务队列为空。
  4. 微任务队列处理完后,才会从宏任务队列中取出一个宏任务并执行。
  5. 重复步骤 3 和 4,直到任务队列中的所有任务都被执行完毕。

例如:

console.log('同步任务 1');
setTimeout(() => {
    console.log('宏任务 1');
}, 0);
Promise.resolve().then(() => {
    console.log('微任务 1');
});
console.log('同步任务 2');

在这个例子中,首先执行“同步任务 1”和“同步任务 2”。然后,由于setTimeout是宏任务,它会被放入宏任务队列中等待执行。同时,Promise.resolve().then()是微任务,会被放入微任务队列中。当同步任务执行完毕后,会先执行微任务队列中的“微任务 1”,然后才会从宏任务队列中取出“宏任务 1”执行。

面试题:

console.log('同步任务 start');

setTimeout(() => {
    console.log('宏任务 1');
    Promise.resolve().then(() => {
        console.log('微任务 within 宏任务 1');
    });
}, 0);

Promise.resolve().then(() => {
    console.log('微任务 1');
    setTimeout(() => {
        console.log('宏任务 within 微任务 1');
    }, 0);
});

setTimeout(() => {
    console.log('宏任务 2');
}, 0);

console.log('同步任务 end');

输出结果:

> "同步任务 start"
> "同步任务 end"
> "微任务 1"
> "宏任务 1"
> "微任务 within 宏任务 1"
> "宏任务 2"
> "宏任务 within 微任务 1"

以下是对上述代码执行流程的解释:

  1. 首先,执行同步任务。
    • 输出同步任务 start
    • 接着遇到第二个同步任务,输出同步任务 end
  2. 同步任务执行完毕后,开始检查微任务队列。
    • 此时微任务队列为空,所以继续从宏任务队列中取出任务执行。
  3. 从宏任务队列中取出第一个由setTimeout注册的宏任务执行。
    • 输出宏任务 1
    • 在这个宏任务中,又有一个Promise.resolve().then(),它会注册一个微任务,即console.log('微任务 within 宏任务 1');被放入微任务队列。
  4. 接着,回到宏任务队列继续检查是否还有未执行的宏任务。
    • 由于还有两个由setTimeout注册的宏任务未执行,但是根据事件循环机制,此时要先检查微任务队列。
  5. 微任务队列中有一个任务,即console.log('微任务 within 宏任务 1');,执行这个微任务,输出微任务 within 宏任务 1
  6. 微任务队列处理完毕后,再次从宏任务队列中取出下一个任务执行。
    • 输出宏任务 2
  7. 此时宏任务队列中还有一个任务,是在微任务 1中注册的setTimeout回调,即console.log('宏任务 within 微任务 1');
  8. 执行这个宏任务,输出宏任务 within 微任务 1

标签:异步,同步,console,log,队列,JavaScript,任务,执行
From: https://blog.csdn.net/m0_66492535/article/details/142267943

相关文章

  • 【SpringBoot】调度和执行定时任务--Quartz(超详细)
    Quartz是一个功能强大的任务调度框架,广泛用于在Java应用程序中定时执行任务,同时它支持Cron表达式、持久化任务、集群等特性。以下是Quartz的详细使用教程,包括安装、基本概念、简单示例和高级功能。1.安装Quartz首先,在你的项目中添加Quartz依赖。对于Maven项......
  • 【JavaScript】LeetCode:707设计链表
    文章目录题目内容题目分析(1)获取第n个节点的值(2)头部插入节点(3)尾部插入节点(4)第n个节点前插入节点(5)删除第n个节点完整代码题目内容题目分析添加哨兵节点dummy。在第n个节点前插入节点时,应该找到第n-1个节点(即前一个节点),才能完成插入操作。在删除第n......
  • UART——通用异步接收发送器
    数字系统是以1和0的形式共享和存储信息。要与具有不同架构的多个设备共享此信息,我们需要一种通用的数据交换方法。这就是各种通信协议发挥作用的地方,其中之一就是通用异步接收器发送器(UART)。它是嵌入式电子产品中最常用的通信协议之一。它是一种串行、全双工、异步......
  • 【工具】前端JavaScript代码在线执行器 方便通过网页 手机测试js代码
    【工具】前端JavaScript代码在线执行器方便通过网页手机测试js代码自动补全js代码格式化代码色彩打印日志清空日志待补充<!DOCTYPEhtml><htmllang="zh-CN"><head><metacharset="UTF-8"><metaname="viewport"content="width=device-width,ini......
  • 任务系统demo
    usingSystem;usingSystem.Collections;usingSystem.Collections.Generic;usingSystem.Xml.Serialization;usingUnityEngine;namespaceeTaskHandleSystem{publicinterfaceITaskState{///<summary>///开始任务///......
  • 单机快速部署开源、免费的分布式任务调度系统——Apache DolphinScheduler
    本文主要为大家介绍ApacheDolphinScheduler的单机部署方式,方便大家快速体验。环境准备需要Java环境,这是一个老生常谈的问题,关于Java环境的安装与配置期望大家都可以熟练掌握。验证java环境java-version下载安装包并解压使用wget下载安装包wgethttps://dlcdn.apache.......
  • ajax异步调用
    在JavaScript中,由于`getCity`和`getstations`是异步调用的操作(可能是通过AJAX调用数据),你需要确保在这些操作完成后再调用`uodatastation`方法。可以使用回调函数或者`Promise`来确保顺序执行。假设`getCity`和`getstations`使用`$.ajax`时支持回调函数或返回......
  • 定时循环任务执行
    定时循环任务执行1usingSystem.Timers;23///<summary>4///如果要实现更复杂的功能参见以下5///Cron在线表达式生成器(https://cron.ciding.cc/)6///</summary>7publicclassScheduledTaskExecutor8{9privateList<TaskInfo>tasks......
  • PbootCMS程序利用计划任务执行网站自动推送到百度
    <?phpheader('Content-Type:text/html;charset=utf-8');/**只需修改这里面的两个链接**/$xml_url="域名/sitemap.xml";//这里修改你站点的xml地图链接$baidu_api='http://data.zz.baidu.com/urls?site=域名&token=123456789';//这里修改为你在百度站长获取到的推送接......
  • 一个linux下监听某个端口并拉起任务的shell脚本
    ​  创建监控脚本:#!/bin/bash#定义要监控的端口号PORT=8011whiletrue;do#使用netstat或ss命令检查端口是否存在if!ss-tuln|grep-q":$PORT";thenecho"$(date)端口$PORT不存在,正在尝试重启服务...">>./port_monitor.l......