广告
返回顶部
首页 > 资讯 > 前端开发 > node.js >JavaScript异步编程的使用
  • 137
分享到

JavaScript异步编程的使用

2024-04-02 19:04:59 137人浏览 薄情痞子
摘要

这篇文章主要介绍“javascript异步编程的使用”,在日常操作中,相信很多人在JavaScript异步编程的使用问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”JavaSc

这篇文章主要介绍“javascript异步编程的使用”,在日常操作中,相信很多人在JavaScript异步编程的使用问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”JavaScript异步编程的使用”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!

按照维基百科上的解释:独立于主控制流之外发生的事件就叫做异步。比如说有一段顺序执行的代码

void function main() {   fA();   fB(); }();

fA => fB 是顺序执行的,永远都是 fA 在 fB 的前面执行,他们就是 同步 的关系。加入这时使用 setTimeout 将 fB  延后

void function main() {   setTimeout(fA, 1000);   fB(); }();

这时,fA 相对于 fB 就是异步的。main 函数只是声明了要在一秒后执行一次 fA,而并没有立刻执行它。这时,fA 的控制流就独立于 main  之外。

JavaScript——天生异步的语言

因为 setTimeout 的存在,至少在被 ECMA 标准化的那一刻起,JavaScript 就支持异步编程了。与其他语言的 sleep  不同,setTimeout 是异步的——它不会阻挡当前程序继续往下执行。

然而异步编程真正发展壮大,ajax 的流行功不可没。Ajax 中的 A(Asynchronous)真正点到了异步的概念——这还是 IE5、IE6  的时代。

回调函数——异步编程之痛

异步任务执行完毕之后怎样通知开发者呢?回调函数是最朴素的,容易想到的实现方式。于是从异步编程诞生的那一刻起,它就和回调函数绑在了一起。

例如 setTimeout。这个函数会起一个定时器,在超过指定时间后执行指定的函数。比如在一秒后输出数字 1,代码如下:

setTimeout(() => {   console.log(1); }, 1000);

常规用法。如果需求有变,需要每秒输出一个数字(当然不是用 setInterval),JavaScript 的初学者可能会写出这样的代码:

for (let i = 1; i < 10; ++i) {   setTimeout(() => { // 错误!     console.log(i);   }, 1000); }

执行结果是等待 1 秒后,一次性输出了所有结果。因为这里的循环是同时启了 10 个定时器,每个定时器都等待 1 秒,结果当然是所有定时器在 1  秒后同时超时,触发回调函数。

解法也简单,只需要在前一个定时器超时后再启动另一个定时器,代码如下:

setTimeout(() => {   console.log(1);   setTimeout(() => {     console.log(2);     setTimeout(() => {       console.log(3);       setTimeout(() => {         console.log(4);         setTimeout(() => {           console.log(5);           setTimeout(() => {             // ...           }, 1000);         }, 1000);       }, 1000)     }, 1000)   }, 1000) }, 1000);

层层嵌套,结果就是这样的漏斗形代码。可能有人想到了新标准中的 Promise,可以改写如下:

function timeout(delay) {   return new Promise(resolve => {     setTimeout(resolve, delay);   }); }  timeout(1000).then(() => {   console.log(1);   return timeout(1000); }).then(() => {   console.log(2);   return timeout(1000); }).then(() => {   console.log(3);   return timeout(1000); }).then(() => {   console.log(4);   return timeout(1000); }).then(() => {   console.log(5);   return timeout(1000); }).then(() => {   // .. });

漏斗形代码是没了,但代码量本身并没减少多少。Promise 并没能干掉回调函数。

因为回调函数的存在,循环就无法使用。不能循环,那么只能考虑递归了,解法如下:

let i = 1; function next() {   console.log(i);   if (++i < 10) {     setTimeout(next, 1000);   } } setTimeout(next, 1000);

注意虽然写法是递归,但由于 next 函数都是由浏览器调用的,所以实际上并没有递归函数的调用栈结构。

Generator&mdash;&mdash;JavaScript 中的半协程

很多语言都引入了协程来简化异步编程,JavaScript 也有类似的概念,叫做 Generator。

MDN 上的解释:Generator 是一种可以中途退出之后重入的函数。他们的函数上下文在每次重入后会被保持。简而言之,Generator 与普通  Function ***的区别就是:Generator 自身保留上次调用的状态。

举个简单的例子:

function *gen() {   yield 1;   yield 2;   return 3; }  void function main() {   var iter = gen();   console.log(iter.next().value);   console.log(iter.next().value);   console.log(iter.next().value); }();

代码的执行顺序是这样:

  1. 鸿蒙官方战略合作共建——HarmonyOS技术社区

  2. 请求 gen,得到一个迭代器 iter。注意此时并未真正执行 gen 的函数体。

  3. 调用 iter.next(),执行 gen 的函数体。

  4. 遇到 yield 1,将 1 返回,iter.next() 的返回值即为 { done: false, value: 1 },输出 1

  5. 调用 iter.next()。从上次 yield 出去的地方继续往下执行 gen。

  6. 遇到 yield 2,将 2 返回,iter.next() 的返回值即为 { done: false, value: 2 },输出 2

  7. 调用 iter.next()。从上次 yield 出去的地方继续往下执行 gen。

  8. 遇到 return 3,将 3 返回,return 表示整个函数已经执行完毕。iter.next() 的返回值即为 { done: true,  value: 3 },输出 3

调用 Generator 函数只会返回一个迭代器,当用户主动调用了 iter.next() 后,这个 Generator 函数才会真正执行。

你可以使用 for ... of 遍历一个 iterator,例如

for (var i of gen()) {   console.log(i); }

输出 1 2,*** return 3 的结果不算在内。想用 Generator 的各项生成一个数组也很简单,Array.from(gen()) 或直接用  [...gen()] 即可,生成 [1, 2] 同样不包含***的 return 3。

Generator 是异步的吗

Generator 也叫半协程(semicoroutine),自然与异步关系匪浅。那么 Generator 是异步的吗?

既是也不是。前面提到,异步是相对的,例如上面的例子

function *gen() {   yield 1;   yield 2;   return 3; }  void function main() {   var iter = gen();   console.log(iter.next().value);   console.log(iter.next().value);   console.log(iter.next().value); }();

我们可以很直观的看到,gen 的方法体与 main 的方法体在交替执行,所以可以肯定的说,gen 相对于 main  是异步执行的。然而此段过程中,整个控制流都没有交回给浏览器,所以说 gen 和 main 相对于浏览器是同步执行的。

用 Generator 简化异步代码

回到最初的问题:

for (let i = 0; i < 10; ++i) {   setTimeout(() => {     console.log(i);   }, 1000);   // 等待上面 setTimeout 执行完毕 }

关键在于如何等待前面的 setTimeout 触发回调后再执行下一轮循环。如果使用 Generator,我们可以考虑在 setTimeout 后  yield 出去(控制流返还给浏览器),然后在 setTimeout 触发的回调函数中 next,将控制流交还回给代码,执行下一段循环。

let iter;  function* run() {   for (let i = 1; i < 10; ++i) {     setTimeout(() => iter.next(), 1000);     yield; // 等待上面 setTimeout 执行完毕     console.log(i);   } }  iter = run(); iter.next();

代码的执行顺序是这样:

  • 请求 run,得到一个迭代器 iter。注意此时并未真正执行 run 的函数体。

  • 调用 iter.next(),执行 run 的函数体。

  • 循环开始,i 初始化为 1。

  • 执行 setTimeout,启动一个定时器,回调函数延后 1 秒执行。

  • 遇到 yield(即 yield undefined),控制流返回到***的 iter.next()  之后。因为后面没有其他代码了,浏览器获得控制权,响应用户事件,执行其他异步代码等。

  • 1 秒后,setTimeout 超时,执行回调函数 () => iter.next()。

  • 调用 iter.next()。从上次 yield 出去的地方继续往下执行,即 console.log(i),输出 i 的值。

  • 一次循环结束,i 自增为 2,回到第 4 步继续执行

  • &hellip;&hellip;

这样即实现了类似同步 sleep 的要求。

async、await&mdash;&mdash;用同步语法写异步代码

上面的代码毕竟需要手工定义迭代器变量,还要手工 next;更重要的是与 setTimeout 紧耦合,无法通用。

我们知道 Promise 是异步编程的未来。能不能把 Promise 和 Generator 结合使用呢?这样考虑的结果就是 async 函数。

用 async 得到代码如下

function timeout(delay) {   return new Promise(resolve => {     setTimeout(resolve, delay);   }); }  async function run() {   for (let i = 1; i < 10; ++i) {     await timeout(1000);     console.log(i);   } } run();

按照 Chrome 的设计文档,async 函数内部就是被编译为 Generator 执行的。run 函数本身会返回一个  Promise,用于使主调函数得知 run 函数什么时候执行完毕。所以 run() 后面也可以 .then(xxx),甚至直接 await run()。

注意有时候我们的确需要几个异步事件并行执行(比如调用两个接口,等两个接口都返回后执行后续代码),这时就不要过度使用 await,例如:

const a = await queryA(); // 等待 queryA 执行完毕后 const b = await queryB(); // 执行 queryB doSomething(a, b);

这时 queryA 和 queryB 就是串行执行的。可以略作修改:

const promiseA = queryA(); // 执行 queryA const b = await queryB(); // 执行 queryB 并等待其执行结束。这时同时 queryA 也在执行。 const a = await promiseA(); // 这时 queryB 已经执行结束。继续等待 queryA 执行结束 doSomething(a, b);

我个人比较喜欢如下写法:

const [ a, b ] = await Promise.all([ queryA(), queryB() ]); doSomething(a, b);

将 await 和 Promise 结合使用,效果更佳!

结束语

如今 async 函数已经被各大主流浏览器实现(除了 IE)。如果要兼容旧版浏览器,可以使用 babel 将其编译为  Generator。如果还要兼容只支持 ES5 的浏览器,还可以继续把 Generator 编译为 ES5。编译后的代码量比较大,小心代码膨胀。

如果是用 node 写 Server,那就不用纠结了直接用就是了。koa 是用 async 是你的好帮手。

到此,关于“JavaScript异步编程的使用”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注编程网网站,小编会继续努力为大家带来更多实用的文章!

--结束END--

本文标题: JavaScript异步编程的使用

本文链接: https://www.lsjlt.com/news/66518.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • JavaScript异步编程的使用
    这篇文章主要介绍“JavaScript异步编程的使用”,在日常操作中,相信很多人在JavaScript异步编程的使用问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”JavaSc...
    99+
    2022-10-19
  • JavaScript异步编程的用法
    这篇文章将为大家详细讲解有关JavaScript异步编程的用法,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。在一年前初学js的时候,看过很多关于异步编程的讲解。但是由于实...
    99+
    2022-10-19
  • JavaScript异步编程之Promise的初步使用详解
    1. 概述 Promise对象是ES6提出的的异步编程的规范。说到异步编程,就不得不说说同步和异步这两个概念。 从字面意思理解同步编程的话,似乎指的是两个任务同步运行,如果这样理解就...
    99+
    2022-11-12
  • 异步JavaScript编程中的Promise使用方法
    异步? 我在很多地方都看到过异步(Asynchronous)这个词,但在我还不是很理解这个概念的时候,却发现自己常常会被当做“已经很清楚”(* ̄? ̄)。 如果你也有类似的情况,没关系,搜索一下这个...
    99+
    2022-06-04
    使用方法 JavaScript Promise
  • Javascript异步编程简介
    这篇文章主要介绍“Javascript异步编程简介”,在日常操作中,相信很多人在Javascript异步编程简介问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Javascri...
    99+
    2022-10-19
  • Laravel和JavaScript的异步编程与Python的异步编程有何不同?
    随着计算机技术的不断发展,异步编程已经成为了现代编程中的一个非常重要的概念。许多编程语言都提供了异步编程的支持,如Laravel、JavaScript和Python等。虽然它们都可以实现异步编程,但是它们之间的实现方式有所不同。本文将探讨...
    99+
    2023-09-08
    异步编程 laravel javascript
  • Javascript异步编程是怎样的
    本篇文章给大家分享的是有关Javascript异步编程是怎样的,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。这可能是个比较深的话题。何谓异步?...
    99+
    2022-10-19
  • 异步的含义以及JavaScript异步编程的方法
    本篇内容主要讲解“异步的含义以及JavaScript异步编程的方法”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“异步的含义以及JavaScript异步编程的方法...
    99+
    2022-10-19
  • 如何在Python异步编程中使用Laravel和JavaScript?
    Python异步编程在近年来越来越受到开发者的重视,因为它可以提高程序的性能和吞吐量,同时也能够更好地应对高并发的场景。而在异步编程中,Laravel和JavaScript也是非常常用的技术。本文将介绍如何在Python异步编程中使用Lar...
    99+
    2023-09-08
    异步编程 laravel javascript
  • JavaScript中异步编程的示例分析
    这篇文章给大家分享的是有关JavaScript中异步编程的示例分析的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。目的提升开发效率,编写易维护的代码引子问题请求时候为什么页面卡死??$.ajax({ &n...
    99+
    2023-06-15
  • Laravel和JavaScript如何与Python异步编程一起使用?
    在现代Web应用程序中,异步编程是一个非常重要的话题。随着用户对Web应用程序的期望越来越高,我们需要确保我们的应用程序能够快速地响应和处理大量的数据。异步编程是实现这一目标的关键。 异步编程是指在执行任务时,可以在等待任务完成时执行其他...
    99+
    2023-09-08
    异步编程 laravel javascript
  • 如何在 JavaScript 中使用异步编程提高性能?
    JavaScript 是一种单线程的语言,这意味着它只能在一个时间点执行一个任务。这个限制会对性能产生负面影响,尤其是在处理大量数据和进行复杂计算的时候。但是,异步编程可以帮助我们在不阻塞主线程的情况下提高 JavaScript 的性能。本...
    99+
    2023-10-02
    异步编程 javascript linux
  • 如何使 Python 异步编程更加响应 javascript?
    Python 异步编程和 JavaScript 异步编程都是非常流行的编程模式,它们都可以提高程序的效率和响应速度。但是,Python 异步编程在处理高并发和网络 IO 时,可能会出现性能瓶颈,不如 JavaScript 那么出色。那么,如...
    99+
    2023-07-27
    异步编程 响应 javascript
  • javascript异步编程有哪些方式
    这篇文章主要为大家展示了“javascript异步编程有哪些方式”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“javascript异步编程有哪些方式”这篇文章吧...
    99+
    2022-10-19
  • Python 异步编程能否响应 javascript?
    随着Web应用程序的普及,JavaScript已经成为了前端开发的标配语言。而Python也因其易学易用而成为了数据科学、Web后端等领域的热门语言。在这两个语言的交汇点上,我们不禁要问一句:Python 异步编程能否响应 JavaScri...
    99+
    2023-07-27
    异步编程 响应 javascript
  • Javascript异步编程之你真的懂Promise吗
    目录前言基本用法语法错误处理Promise链式调用async & await常用的方法1、Promise.resolve()2、Promise.reject()3、Promi...
    99+
    2022-11-12
  • 异步编程的秘密:Python 和 Javascript 中的缓存使用技巧
    在当今的互联网时代,我们面对的数据量越来越大,数据处理的速度也愈发重要。异步编程就是为了解决这个问题而应运而生的一种编程思想,它可以提高程序的效率和性能。在异步编程中,缓存技术是非常重要的一部分,它可以加速数据的读取和处理,提升程序的运行...
    99+
    2023-06-27
    javascript 异步编程 缓存
  • Dart中的异步编程怎么使用
    这篇文章主要讲解了“Dart中的异步编程怎么使用”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Dart中的异步编程怎么使用”吧!一 事件循环flutter 就是运行在一个root isola...
    99+
    2023-07-06
  • Java 异步编程:快速掌握异步编程的精髓!
    Java 是一种高度可扩展的编程语言,拥有大量的库和框架,使得开发人员能够快速构建复杂的应用程序。其中,异步编程是 Java 中非常重要的一种编程模型,可以帮助我们构建高效、高性能的应用程序。本文将介绍 Java 异步编程的基本概念,并演...
    99+
    2023-09-29
    异步编程 打包 load
  • JavaScript异步编程操作实现介绍
    目录异步编程同步模式与异步模式同步模式(Synchronous)异步模式(Asynchronous)回调函数PromisePromise基本用法Promise使用案例Promise常...
    99+
    2022-11-13
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作