详解Javascript中async/await是如何工作的

详解Javascript中async/await是如何工作的

相关推荐:《javascript视频教程》

async / await是ES7的重要特性之一,也是目前社区里公认的优秀异步解决方案。目前,async / await这个特性已经是stage 3的建议,可以看看TC39的进度,本篇文章将分享async / await是如何工作的,阅读本文前,希望你具备Promise、generator、yield等ES6的相关知识。

在详细介绍async / await之前,先回顾下目前在ES6中比较好的异步处理办法。下面的例子中数据请求用Node.js中的request模块,数据接口采用Github v3 api文档提供的repo代码仓库详情API作为例子演示。

Promise对异步的处理

虽然Node.js的异步IO带来了对高并发的良好支持,同时也让“回调”成为灾难,很容易造成回调地狱。传统的方式比如使用具名函数,虽然可以减少嵌套的层数,让代码看起来比较清晰。但是会造成比较差的编码和调试体验,你需要经常使用用ctrl + f去寻找某个具名函数的定义,这使得IDE窗口经常上下来回跳动。使用Promise之后,可以很好的减少嵌套的层数。另外Promise的实现采用了状态机,在函数里面可以很好的通过resolve和reject进行流程控制,你可以按照顺序链式的去执行一系列代码逻辑了。下面是使用Promise的一个例子:

立即学习“Java免费学习笔记(深入)”;

const request = require('request');// 请求的url和headerconst options = {  url: 'https://api.github.com/repos/cpselvis/zhihu-crawler',  headers: {    'User-Agent': 'request'  }};// 获取仓库信息const getRepoData = () => {  return new Promise((resolve, reject) => {    request(options, (err, res, body) => {      if (err) {        reject(err);      }      resolve(body);    });  });};getRepoData()  .then((result) => console.log(result);)  .catch((reason) => console.error(reason););// 此处如果是多个Promise顺序执行的话,如下:// 每个then里面去执行下一个promise// getRepoData()//   .then((value2) => {return promise2})//   .then((value3) => {return promise3})//   .then((x) => console.log(x))

登录后复制

不过Promise仍然存在缺陷,它只是减少了嵌套,并不能完全消除嵌套。举个例子,对于多个promise串行执行的情况,第一个promise的逻辑执行完之后,我们需要在它的then函数里面去执行第二个promise,这个时候会产生一层嵌套。另外,采用Promise的代码看起来依然是异步的,如果写的代码如果能够变成同步该多好啊!

Generator对异步的处理

谈到generator,你应该不会对它感到陌生。在Node.js中对于回调的处理,我们经常用的TJ / Co就是使用generator结合promise来实现的,co是coroutine的简称,借鉴于python、lua等语言中的协程。它可以将异步的代码逻辑写成同步的方式,这使得代码的阅读和组织变得更加清晰,也便于调试。

const co = require('co');const request = require('request');const options = {  url: 'https://api.github.com/repos/cpselvis/zhihu-crawler',  headers: {    'User-Agent': 'request'  }};// yield后面是一个生成器 generatorconst getRepoData = function* () {  return new Promise((resolve, reject) => {    request(options, (err, res, body) => {      if (err) {        reject(err);      }      resolve(body);    });  });};co(function* () {  const result = yield getRepoData;  // ... 如果有多个异步流程,可以放在这里,比如  // const r1 = yield getR1;  // const r2 = yield getR2;  // const r3 = yield getR3;  // 每个yield相当于暂停,执行yield之后会等待它后面的generator返回值之后再执行后面其它的yield逻辑。  return result;}).then(function (value) {  console.log(value);}, function (err) {  console.error(err.stack);});

登录后复制

async / await对异步的处理

虽然co是社区里面的优秀异步解决方案,但是并不是语言标准,只是一个过渡方案。ES7语言层面提供async / await去解决语言层面的难题。目前async / await 在 IE edge中已经可以直接使用了,但是chrome和Node.js还没有支持。幸运的是,babel已经支持async的transform了,所以我们使用的时候引入babel就行。在开始之前我们需要引入以下的package,preset-stage-3里就有我们需要的async/await的编译文件。

无论是在Browser还是Node.js端都需要安装下面的包。

$ npm install babel-core --save$ npm install babel-preset-es2015 --save$ npm install babel-preset-stage-3 --save

登录后复制

这里推荐使用babel官方提供的require hook方法。就是通过require进来后,接下来的文件进行require的时候都会经过Babel的处理。因为我们知道CommonJs是同步的模块依赖,所以也是可行的方法。这个时候,需要编写两个文件,一个是启动的js文件,另外一个是真正执行程序的js文件。

启动文件index.js

require('babel-core/register');require('./async.js');

登录后复制

真正执行程序的async.js

const request = require('request');const options = {  url: 'https://api.github.com/repos/cpselvis/zhihu-crawler',  headers: {    'User-Agent': 'request'  }};const getRepoData = () => {  return new Promise((resolve, reject) => {    request(options, (err, res, body) => {      if (err) {        reject(err);      }      resolve(body);    });  });};async function asyncFun() { try {    const value = await getRepoData();    // ... 和上面的yield类似,如果有多个异步流程,可以放在这里,比如    // const r1 = await getR1();    // const r2 = await getR2();    // const r3 = await getR3();    // 每个await相当于暂停,执行await之后会等待它后面的    //函数(不是generator)返回值之后再执行后面其它的await逻辑。    return value;  } catch (err) {    console.log(err);  }}asyncFun().then(x => console.log(`x: ${x}`)).catch(err => console.error(err));

登录后复制

注意点:

async用来申明里面包裹的内容可以进行同步的方式执行,await则是进行执行顺序控制,每次执行一个await,程序都会暂停等待await返回值,然后再执行之后的await。await后面调用的函数需要返回一个promise,另外这个函数是一个普通的函数即可,而不是generator。await只能用在async函数之中,用在普通函数中会报错。await命令后面的 Promise 对象,运行结果可能是 rejected,所以最好把 await 命令放在 try…catch 代码块中。

其实,async / await的用法和co差不多,await和yield都是表示暂停,外面包裹一层async 或者 co来表示里面的代码可以采用同步的方式进行处理。不过async / await里面的await后面跟着的函数不需要额外处理,co是需要将它写成一个generator的。

更多编程相关知识,请访问:编程学习!!

以上就是详解Javascript中async/await是如何工作的的详细内容,更多请关注【创想鸟】其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至253000106@qq.com举报,一经查实,本站将立刻删除。

发布者:PHP中文网,转转请注明出处:https://www.chuangxiangniao.com/p/2718691.html

(0)
上一篇 2025年3月7日 22:18:06
下一篇 2025年3月7日 18:58:40

AD推荐 黄金广告位招租... 更多推荐

相关推荐

  • JavaScript去除拼接字符串末尾符号的方法

    前言:在JS中,有时需要进行字符串的拼接,而拼接的字符串以某种符号分隔,在拼接好的字符串末尾会多出一个分隔符,这时我们可以采取以下几种方法来去除末尾的分隔符。 更多编程相关知识,请访问:编程学习!! 方法一:使用substring()  和…

    2025年3月7日 编程技术
    200
  • 详解使用 Set 来提高JS代码性能的方法

    我确信有很多开发人员坚持使用基本的全局对象:数字,字符串,对象,数组和布尔值。对于许多用例,这些都是需要的。 但是如果想让你的代码尽可能快速和可扩展,那么这些基本类型并不总是足够好。 在本文中,我们将讨论JS 中Set对象如何让代码更快— …

    2025年3月7日
    100
  • 详细了解JavaScript中的回调函数

    相关推荐:《javascript视频教程》 回调函数是每个前端程序员都应该知道的概念之一。回调可用于数组、计时器函数、promise、事件处理中。 本文将会解释回调函数的概念,同时帮你区分两种回调:同步和异步。 回调函数 首先写一个向人打招…

    2025年3月7日
    200
  • Javascript实现复制动作的几种方法(总结)

    本篇文章给大家介绍一下javascript 实现复制(copy)动作的几种方法。有一定的参考价值,有需要的朋友可以参考一下,希望对大家有所帮助。 Javascript 实现复制(Copy)动作大全 一、实现点击按钮,复制文本框中的的内容 f…

    2025年3月7日
    200
  • 详解JavaScript降低函数复杂度的方法

    JavaScript 是一种易于学习的编程语言,编写运行并执行某些操作的程序很容易。然而,要编写一段干净的JavaScript 代码是很困难的。 在本文中,我们将研究如何降低函数复杂度。 将重复的代码移到同个位置 我们应该将重复的代码提取出…

    2025年3月7日
    200
  • 怎么遍历DOM

    相关推荐:《javascript视频教程》 我们知道可以使用document对象的内置方法通过ID,类,标签名和查询选择器来访问HTML元素。 DOM 是由节点树构成的,document 节点位于根,其他每个节点(包括元素,注释和文本节点)…

    2025年3月7日
    200
  • 实现原生js实现轮播图

    免费学习推荐:javascript视频教程 使用原生js实现轮播图 今天分享一个使用原生JS实现轮播图的案例,并且配上比较详细的过程讲解,欢迎小伙伴的浏览和批评指正。静态效果图如下: 核心思想 将一些图片在一行中平铺,然后计算偏移量再利用定…

    2025年3月7日 编程技术
    200
  • 记录JavaScript的学习笔记

    免费学习推荐:javascript学习教程 一、什么是JavaScript 1-1、JavaScript实现 虽然JavaScript和ECMAScript基本上是同义词,但JavaScript远不限于ECMA-262所定义的那样。完整的J…

    2025年3月7日
    200
  • DOM节点和元素之间有什么区别

    相关推荐:《javascript视频教程》 文档对象模型(DOM)是一个将HTML或XML文档视为树形结构的接口,其中每个节点都是文档的一个对象。DOM还提供了一组方法来查询树、改变结构、样式。 DOM 还使用术语元素(Element)它与…

    2025年3月7日
    200
  • JavaScript实现UTF-8编解码

    免费学习推荐:javascript视频教程 首先简单介绍一下UTF-8。UTF-8以字节为单位对Unicode进行编码。UTF-8的特点是对不同范围的字符使用不同长度的编码。对于0x00-0x7F之间的字符,UTF-8编码与ASCII编码完…

    2025年3月7日
    200

发表回复

登录后才能评论