js 程序执行与顺序实现详解

JS程序执行与顺序实现详解

JS是一门单线程语言,指在一个时间只执行一个任务。虽然JS是单线程语言,但是它可以利用事件循环和回调实现异步编程。

1. JS代码的执行顺序

JS代码是从上往下一行一行执行的,但是在执行JS代码时,遇到如下情况就会把当前任务挂起,去执行其他任务:

  1. 等待Web API返回结果,例如:发起Ajax请求等。
  2. 等待定时器。
  3. 等待事件发生。

1.1 Web API的异步处理

当执行代码中遇到Web API时,JS并不会一直等待Web API的完成,而是先将代码执行完毕,然后将Web API相关的回调函数加入异步队列中排队等待Web API返回结果,待结果返回后,JS引擎从异步队列中读取相应回调函数。

示例:

console.log('start');
setTimeout(function() {
  console.log('callback');
}, 1000);
console.log('end');

该示例中,先输出“start”,实际上是同步任务。接着执行定时器,将回调函数异步添加到任务队列中,然后输出“end”。但是需要等待1秒后,从异步队列中读取回调函数,输出“callback”。

1.2 Promise的异步处理

Promise是JS提供的异步编程的解决方案,ES6中的新特性。Promise可以将异步代码封装成Promise对象,实现更为优雅的异步代码的书写。

示例:

console.log('start');
new Promise((resolve, reject) => {
  console.log('promise start');
  setTimeout(() => {
    resolve('promise callback');
  }, 1000);
}).then((res) => {
  console.log('promise then:', res);
});
console.log('end');

该示例中,Promise的执行流程:

  1. 首先输出“start”,接着执行Promise构造函数中的代码,输出“promise start”。
  2. 调用setTimeout函数,将回调函数异步加入任务队列,会异步执行回调函数。
  3. 输出“end”。
  4. 等待1秒后,从异步队列中读取回调函数,resolve Promise,将Promise对象标记为fulfill状态,同时执行then方法中的回调函数,输出“promise then:promise callback”。

1.3 await/async

async/await是ES8中的特性,比Promise更为优雅,在异步编程中经常被使用。async/await的实现原理就是Promise。

示例:

console.log('start');

function promise() {
  return new Promise((resolve, reject) => {
    console.log('promise start');
    setTimeout(() => {
      resolve('promise callback');
    }, 1000);
  });
}

async function asyncFunction() {
  let res = await promise();
  console.log('async function:', res);
}

asyncFunction();

console.log('end');

该示例中,async/await的执行流程:

  1. 首先输出“start”,接着执行promise函数中的代码,输出“promise start”。
  2. 调用setTimeout函数,将回调函数异步加入任务队列,会异步执行回调函数。
  3. 输出“end”。
  4. 等待1秒后,从异步队列中读取回调函数,resolve Promise,将Promise对象标记为fulfill状态。
  5. await promise()执行完毕后,执行async函数中的后续代码,输出“async function:promise callback”。

2. JS事件循环机制

JS的事件循环机制是负责读取异步队列中的回调函数,并在合适的时间将其加入调用栈中,执行回调函数。

2.1 微任务

微任务包含Promise回调函数、Node.js中的process.nextTick函数以及MutationObserver回调函数等,微任务中的回调函数执行速度比较快。

示例:

Promise.resolve().then(() => {
  console.log('promise callback 1');
}).then(() => {
  console.log('promise callback 2');
});

process.nextTick(() => {
  console.log('process.nextTick callback');
});

console.log('start');

该示例中,输出顺序为:

  1. start
  2. process.nextTick callback
  3. promise callback 1
  4. promise callback 2

2.2 宏任务

宏任务包含定时器回调函数、事件回调函数等,宏任务执行速度较慢。

示例:

console.log('start');

setTimeout(() => {
  console.log('setTimout callback');
}, 0);

Promise.resolve().then(() => {
  console.log('promise callback 1');
}).then(() => {
  console.log('promise callback 2');
});

console.log('end');

该示例中,输出顺序为:

  1. start
  2. end
  3. promise callback 1
  4. promise callback 2
  5. setTimout callback

3. JS代码执行顺序的总结

JS代码执行时:

  1. 如果遇到异步操作,则将回调函数加入异步队列中。
  2. 当同步代码执行完毕后,调用栈为空,JS引擎会读取异步队列中的回调函数,按照事件循环机制的规则取出执行。
  3. 执行完毕后,再次读取异步队列中的回调函数,如此反复,直到异步队列为空。

注意:代码的执行顺序不是绝对的,各种环境的实现可能会有所不同。

4. 小结

JS的异步执行需要遵守事件循环机制,异步操作将会加入异步队列,在适当的时间由任务队列中的事件循环机制调用栈中执行。虽然JS是单线程执行,但异步编程使代码的执行更为优雅和高效。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:js 程序执行与顺序实现详解 - Python技术站

(0)
上一篇 2023年5月27日
下一篇 2023年5月27日

相关文章

  • $()JS小技巧

    $()JS小技巧 在前端开发中,我们经常需要对DOM元素进行操作,而jQuery库可以帮助我们更方便地实现这些操作。其中一个最常用的方法是$(),它可以获取DOM元素并对其进行操作。 基本语法 $()是jQuery的一种基本语法,它可以通过选择器来选取HTML元素,并返回一个jQuery对象。基本语法如下: $(selector).action() 其中的s…

    JavaScript 2023年5月18日
    00
  • JSON的parse()方法介绍

    当我们获取API返回数据或者前端传输数据时,常常会遇到JSON格式的字符串,如果我们要将其转换成JavaScript对象,就需要使用JSON的parse()方法。下面就来详细讲解一下parse()方法的使用。 JSON的parse()方法介绍 在 JavaScript 中,JSON.parse() 方法将 JSON 字符串转换为 JavaScript 对象。…

    JavaScript 2023年5月27日
    00
  • js实现GridView单选效果自动设置交替行、选中行、鼠标移动行背景色

    实现GridView单选效果自动设置交替行、选中行、鼠标移动行背景色的过程分为以下几步: HTML结构构建 先构建一个table,需要注意每个单元格需要有一个唯一的id值,如下所示: <table id="myGridview"> <thead> <tr> <th>ID</th>…

    JavaScript 2023年6月11日
    00
  • 详解Chrome 实用调试技巧

    详解Chrome 实用调试技巧 调试是开发者日常工作中必不可少的一环,Chrome 浏览器的调试工具内置了非常丰富的功能,本文将详细讲解怎样通过 Chrome 调试工具来提高调试效率。 前置条件 本文所讲述的内容需要您先掌握 Chrome 调试工具的基础使用方法,如果您对此还不熟练,可以参考 Chrome 调试指南。 常见的调试技巧 1. 断点调试 通过在源…

    JavaScript 2023年6月11日
    00
  • Java matches类,Pattern类及matcher类用法示例

    Java中的matches、Pattern和Matcher类一起可以实现Java中正则表达式的匹配操作。 matches类是String类的一种方法,在Java中用于测试字符串是否与指定的正则表达式匹配。如果匹配则返回true,否则返回false。 Pattern类是Java中正则表达式的编译表示。可以把一个正则表达式编译成Pattern对象,然后可以使用P…

    JavaScript 2023年6月10日
    00
  • JavaScript进阶之前端文件上传和下载示例详解

    JavaScript进阶之前端文件上传和下载示例详解 本文将详细讲解前端文件上传和下载的过程和实现方法,包括如何使用HTML5 FormData API、AJAX和原生JavaScript来完成文件上传和下载功能的开发。 文件上传 文件上传是我们日常开发中常用的功能之一。下面我们通过两个示例来讲解文件上传的实现。 示例1:上传图片并预览 HTML部分 &lt…

    JavaScript 2023年5月27日
    00
  • js实现字符串转日期格式的方法

    下面是实现字符串转日期格式的方法的完整攻略: 步骤一:创建日期对象 字符串转日期格式,我们需要先将字符串转为日期对象,再对日期对象进行格式化操作。我们可以通过Date对象来创建日期对象。 let dateStr = ‘2021-12-31’; let dateObj = new Date(dateStr); console.log(dateObj); 上面的…

    JavaScript 2023年5月27日
    00
  • Javascript将图片的绝对路径转换为base64编码的方法

    将图片的绝对路径转换为base64编码的方法可以使用Javascript的Canvas对象来实现。具体过程如下: 步骤 1:创建一个Image对象 首先,我们需要创建一个Image对象,将想要转换成base64编码的图片作为其src属性的值。 const image = new Image(); image.src = ‘https://example.co…

    JavaScript 2023年5月19日
    00
合作推广
合作推广
分享本页
返回顶部