广告
返回顶部
首页 > 资讯 > 前端开发 > VUE >怎么用Async函数简化异步代码
  • 562
分享到

怎么用Async函数简化异步代码

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

今天就跟大家聊聊有关怎么用Async函数简化异步代码,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。Promise 在 javascript 上发布之

今天就跟大家聊聊有关怎么用Async函数简化异步代码,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。

Promise 在 javascript 上发布之初就在互联网上流行了起来, 它们帮开发人员摆脱了回调地狱,解决了在很多地方困扰 JavaScript  开发者的异步问题。

随着 es6 的到来(现在被称作 ES2015),除了引入 Promise  的规范,不需要请求那些数不尽的库之外,我们还有了生成器。生成器可在函数内部停止执行,这意味着可把它们封装在一个多用途的函数中,我们可在代码移动到下一行之前等待异步操作完成。突然你的异步代码可能就开始看起来同步了。

这只是第一步。异步函数因今年加入  ES2017,已进行标准化,本地支持也进一步优化。异步函数的理念是使用生成器进行异步编程,并给出他们自己的语义和语法。因此,你无须使用库来获取封装的实用函数,因为这些都会在后台处理。

运行文章中的 async/await 实例,你需要一个能兼容的浏览器。

运行兼容

在客户端,Chrome、Firefox 和 Opera 能很好地支持异步函数。

怎么用Async函数简化异步代码

从 7.6 版本开始,node.js 默认启用 async/await。

异步函数和生成器对比

这有个使用生成器进行异步编程的实例,用的是 Q 库:

var doAsyncOp = Q.async(function* () {    var val = yield asynchronousOperation();    console.log(val);    return val;  });

Q.async 是个封装函数,处理场景后的事情。其中 * 表示作为一个生成器函数的功能,yield 表示停止函数,并用封装函数代替。Q.async  将会返回一个函数,你可对它赋值,就像赋值 doAsyncOp 一样,随后再调用。

ES7 中的新语法更简洁,操作示例如下:

async function doAsyncOp () {    var val = await asynchronousOperation();         console.log(val);    return val;  };

差异不大,我们删除了一个封装的函数和 * 符号,转而用 async 关键字代替。yield 关键字也被 await  取代。这两个例子事实上做的事是相同的:在 asynchronousOperation 完成之后,赋值给 val,然后进行输出并返回结果。

将 Promises 转换成异步函数

如果我们使用 Vanilla Promises 的话前面的示例将会是什么样?

function doAsyncOp () {    return asynchronousOperation().then(function(val) {      console.log(val);      return val;    });  };

这里有相同的代码行数,但这是因为 then 和给它传递的回调函数增加了很多的额外代码。另一个让人厌烦的是两个 return  关键字。这一直有些事困扰着我,因为它很难弄清楚使用 promises 的函数确切的返回是什么。

就像你看到的,这个函数返回一个 promises,将会赋值给  val,猜一下生成器和异步函数示例做了什么!无论你在这个函数返回了什么,你其实是暗地里返回一个 promise  解析到那个值。如果你根本就没有返回任何值,你暗地里返回的 promise 解析为 undefined。

链式操作

Promise 之所以能受到众人追捧,其中一个方面是因为它能以链式调用的方式把多个异步操作连接起来,避免了嵌入形式的回调。不过 async  函数在这个方面甚至比 Promise 做得还好。

下面演示了如何使用 Promise 来进行链式操作(我们只是简单的多次运行 asynchronousOperation 来进行演示)。

function doAsyncOp() {    return asynchronousOperation()      .then(function(val) {        return asynchronousOperation(val);      })      .then(function(val) {        return asynchronousOperation(val);      })      .then(function(val) {        return asynchronousOperation(val);      });  }

使用 async 函数,只需要像编写同步代码那样调用 asynchronousOperation:

async function doAsyncOp () {    var val = await asynchronousOperation();    val = await asynchronousOperation(val);    val = await asynchronousOperation(val);    return await asynchronousOperation(val);  };

甚至***的 return 语句中都不需要使用 await,因为用或不用,它都返回了包含了可处理终值的 Promise。

并发操作

Promise 还有另一个伟大的特性,它们可以同时进行多个异步操作,等他们全部完成之后再继续进行其它事件。ES2015 规范中提供了  Promise.all(),就是用来干这个事情的。

这里有一个示例:

function doAsyncOp() {    return Promise.all([      asynchronousOperation(),      asynchronousOperation()    ]).then(function(vals) {      vals.forEach(console.log);      return vals;    });  }

Promise.all() 也可以当作 async 函数使用:

async function doAsyncOp() {    var vals = await Promise.all([      asynchronousOperation(),      asynchronousOperation()    ]);    vals.forEach(console.log.bind(console));    return vals;  }

这里就算使用了 Promise.all,代码仍然很清楚。

处理拒绝

Promises 可以被接受(resovled)也可以被拒绝(rejected)。被拒绝的 Promise 可以通过一个函数来处理,这个处理函数要传递给  then,作为其第二个参数,或者传递给 catch 方法。现在我们没有使用 Promise api 中的方法,应该怎么处理拒绝?可以通过 try 和 catch  来处理。使用 async 函数的时候,拒绝被当作错误来传递,这样它们就可以通过 JavaScript 本身支持的错误处理代码来处理。

function doAsyncOp() {    return asynchronousOperation()      .then(function(val) {        return asynchronousOperation(val);      })      .then(function(val) {        return asynchronousOperation(val);      })      .catch(function(err) {        console.error(err);      });  }

这与我们链式处理的示例非常相似,只是把它的***一环改成了调用 catch。如果用 async 函数来写,会像下面这样。

async function doAsyncOp () {    try {      var val = await asynchronousOperation();      val = await asynchronousOperation(val);      return await asynchronousOperation(val);    } catch (err) {      console.err(err);    }  };

它不像其它往 async  函数的转换那样简洁,但是确实跟写同步代码一样。如果你在这里不捕捉错误,它会延着调用链一直向上抛出,直到在某处被捕捉处理。如果它一直未被捕捉,它最终会中止程序并抛出一个运行时错误。Promise  以同样的方式运作,只是拒绝不必当作错误来处理;它们可能只是一个说明错误情况的字符串。如果你不捕捉被创建为错误的拒绝,你会看到一个运行时错误,不过如果你只是使用一个字符串,会失败却不会有输出。

中断 Promise

拒绝原生的 Promise,只需要使用 Promise 构建函数中的 reject 就好,当然也可以直接抛出错误——在 Promise 的构造函数中,在  then 或 catch 的回调中抛出都可以。如果是在其它地方抛出错误,Promise 就管不了了。

这里有一些拒绝 Promise 的示例:

function doAsyncOp() {    return new Promise(function(resolve, reject) {      if (somethinGISBad) {        reject("something is bad");      }      resolve("nothing is bad");    });  }          function doAsyncOp() {    return new Promise(function(resolve, reject) {      if (somethingIsBad) {        reject(new Error("something is bad"));      }      resolve("nothing is bad");    });  }          function doAsyncOp() {    return new Promise(function(resolve, reject) {      if (somethingIsBad) {        throw new Error("something is bad");      }      resolve("nothing is bad");    });  }

一般来说,***使用 new Error,因为它会包含错误相关的其它信息,比如抛出位置的行号,以及可能会有用的调用栈。

这里有一些抛出 Promise 不能捕捉的错误的示例:

function doAsyncOp() {    // the next line will kill execution    throw new Error("something is bad");    return new Promise(function(resolve, reject) {      if (somethingIsBad) {        throw new Error("something is bad");      }      resolve("nothing is bad");    });  }     // assume `doAsyncOp` does not have the killing error  function x() {    var val = doAsyncOp().then(function() {      // this one will work just fine      throw new Error("I just think an error should be here");    });    // this one will kill execution    throw new Error("The more errors, the merrier");    return val;  }

在 async 函数的 Promise 中抛出错误就不会产生有关范围的问题——你可以在 async 函数中随时随地抛出错误,它总会被 Promise  抓住:

async function doAsyncOp() {    // the next line is fine    throw new Error("something is bad");    if (somethingIsBad) {      // this one is Good too      throw new Error("something is bad");    }    return "nothing is bad";  }      // assume `doAsyncOp` does not have the killing error  async function x() {    var val = await doAsyncOp();    // this one will work just fine    throw new Error("I just think an error should be here");    return val;  }

当然,我们永远不会运行到 doAsyncOp 中的第二个错误,也不会运行到 return 语句,因为在那之前抛出的错误已经中止了函数运行。

问题

如果你刚开始使用 async 函数,需要小心嵌套函数的问题。比如,如果你的 async 函数中有另一个函数(通常是回调),你可能认为可以在其中使用  await ,但实际不能。你只能直接在 async 函数中使用 await 。

比如,这段代码无法运行:

async function getAllFiles(fileNames) {    return Promise.all(      fileNames.map(function(fileName) {        var file = await getFileAsync(fileName);        return parse(file);      })    );  }

第 4 行的 await 无效,因为它是在一个普通函数中使用的。不过可以通过为回调函数添加 async 关键字来解决这个问题。

async function getAllFiles(fileNames) {    return Promise.all(      fileNames.map(async function(fileName) {        var file = await getFileAsync(fileName);        return parse(file);      })    );  }

你看到它的时候会觉得理所当然,即便如此,仍然需要小心这种情况。

也许你还想知道等价的使用 Promise 的代码:

function getAllFiles(fileNames) {    return Promise.all(      fileNames.map(function(fileName) {        return getFileAsync(fileName).then(function(file) {          return parse(file);        });      })    );  }

接下来的问题是关于把 async 函数看作同步函数。需要记住的是,async 函数内部的的代码是同步运行的,但是它会立即返回一个  Promise,并继续运行外面的代码,比如:

var a = doAsyncOp(); // one of the working ones from earlier  console.log(a);  a.then(function() {    console.log("`a` finished");  });  console.log("hello");       Promise Object  hello  `a` finished

你会看到 async 函数实际使用了内置的 Promise。这让我们思考 async 函数中的同步行为,其它人可以通过普通的 Promise API  调用我们的 async 函数,也可以使用它们自己的 async 函数来调用。

即使你本身不能使用异步代码,你也可以进行编写或使用工具将其编译为 ES5。 异步函数能让代码更易于阅读,更易于维护。 只要我们有 source  maps,我们可以随时使用更干净的 ES2017 代码。

有许多可以将异步功能(和其他 ES2015+功能)编译成 ES5 代码的工具。 如果您使用的是 Babel,这只是安装 ES2017 preset  的例子。

看完上述内容,你们对怎么用Async函数简化异步代码有进一步的了解吗?如果还想了解更多知识或者相关内容,请关注编程网VUE频道,感谢大家的支持。

--结束END--

本文标题: 怎么用Async函数简化异步代码

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

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

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

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

下载Word文档
猜你喜欢
  • 怎么用Async函数简化异步代码
    今天就跟大家聊聊有关怎么用Async函数简化异步代码,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。Promise 在 JavaScript 上发布之...
    99+
    2022-10-19
  • js异步函数async/awit怎么使用
    异步函数(async/await) 是一种用于处理 JavaScript 异步操作的语法糖,它建立在 Promise 基础之上,使得...
    99+
    2023-09-29
    js
  • JS的异步函数async/await怎么使用
    这篇“JS的异步函数async/await怎么使用”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“JS的异步函数async/a...
    99+
    2023-07-05
  • 一段代码理解Python异步函数async的基本用法
    异步函数的使用规则 正常情况下我们的函数时串行的运行的,这里称之为主函数. 异步函数:与主函数并行运行. Python异步函数即async必须在普通函数的命名前加上async 示...
    99+
    2023-09-11
    python Powered by 金山文档
  • JavaScript异步函数怎么使用
    这篇文章主要介绍了JavaScript异步函数怎么使用的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇JavaScript异步函数怎么使用文章都会有所收获,下面我们一起来看看吧。...
    99+
    2022-10-19
  • java异步函数怎么使用
    这篇文章主要介绍了java异步函数怎么使用的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇java异步函数怎么使用文章都会有所收获,下面我们一起来看看吧。1 低层级 asyncio 索引低层级 API 索引&am...
    99+
    2023-07-05
  • ASP 函数教程索引:如何使用函数来简化您的ASP代码?
    ASP (Active Server Pages) 是一种基于服务器端的脚本语言,它可以与 HTML 一起使用来创建动态网页。ASP 中的函数可以帮助开发者简化代码,提高代码的可读性和可维护性。在本文中,我们将介绍一些常用的 ASP 函数...
    99+
    2023-11-02
    函数 教程 索引
  • c++异步回调函数怎么调用
    在C++中,异步回调函数通常使用函数指针或者函数对象来表示。下面是调用异步回调函数的几种常见方法:1. 使用函数指针:cppvoid...
    99+
    2023-10-20
    c++
  • Python混合怎么使用同步和异步函数
    在协程函数中调用同步函数在协程函数中直接调用同步函数会阻塞事件循环,从而影响整个程序的性能。我们先来看一个例子:以下是使用异步 Web 框架 FastAPI 写的一个例子,FastAPI 是比较快,但不正确的操作将会变得很慢。import ...
    99+
    2023-05-14
    Python
  • PHP开发技术教程:如何使用函数来简化代码?
    PHP是一种强大的编程语言,被广泛应用于Web开发和服务器端编程。在PHP开发中,函数是一种非常有用的工具,可以大大简化代码的编写和维护。在本文中,我们将介绍如何使用函数来简化PHP代码的编写。 一、什么是函数? 函数是一段可重用的代码,可...
    99+
    2023-08-09
    开发技术 教程 函数
  • 如何在PHP、Shell、Django中使用函数来简化您的代码?
    在编写代码时,我们经常会遇到相似的任务,而这些任务通常需要重复的代码来完成。这不仅浪费时间,还会增加代码维护的复杂度。为了简化这个过程,我们可以使用函数来将重复的代码封装起来,使代码更加易于维护和扩展。在本文中,我们将介绍如何在PHP、Sh...
    99+
    2023-09-18
    shell django 函数
  • JQuery异步post上传表单数据的代码怎么写
    今天小编给大家分享一下JQuery异步post上传表单数据的代码怎么写的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。HTML...
    99+
    2023-06-29
  • 怎么用C#代码实现简化QQ聊天窗口
    本文小编为大家详细介绍“怎么用C#代码实现简化QQ聊天窗口”,内容详细,步骤清晰,细节处理妥当,希望这篇“怎么用C#代码实现简化QQ聊天窗口”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。如图样式,详细步骤如下整个...
    99+
    2023-06-29
  • until封装watch常用逻辑简化代码怎么写
    这篇文章主要介绍“until封装watch常用逻辑简化代码怎么写”,在日常操作中,相信很多人在until封装watch常用逻辑简化代码怎么写问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”until封装watc...
    99+
    2023-07-02
  • 批处理BAT加强函数代码怎么用
    小编给大家分享一下批处理BAT加强函数代码怎么用,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!##################################...
    99+
    2023-06-09
  • 怎么使用Lambda表达式简化代码提高生产力
    这篇文章主要介绍“怎么使用Lambda表达式简化代码提高生产力”,在日常操作中,相信很多人在怎么使用Lambda表达式简化代码提高生产力问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”怎么使用Lambda表达式...
    99+
    2023-07-06
  • 在C++ 代码中怎么获取函数调用栈信息
    这篇文章主要介绍“在C++ 代码中怎么获取函数调用栈信息”,在日常操作中,相信很多人在在C++ 代码中怎么获取函数调用栈信息问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”在C++ 代码中怎么获取函数调用栈信息...
    99+
    2023-06-15
  • 用Python代码实现5种最好的、简单的数据可视化分别是怎样的
    这篇文章给大家介绍用Python代码实现5种最好的、简单的数据可视化分别是怎样的,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。数据可视化是数据科学家工作的重要组成部分。在项目的早期阶段,您通常会进行探索性数据分析(ED...
    99+
    2023-06-02
  • 怎么使用初始化种子和unfold迭代函数生成列表
    这篇文章主要介绍“怎么使用初始化种子和unfold迭代函数生成列表”,在日常操作中,相信很多人在怎么使用初始化种子和unfold迭代函数生成列表问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”怎么使用初始化种子...
    99+
    2023-06-25
软考高级职称资格查询
推荐阅读
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作