化繁为简,用几个例子介绍JavaScript异步处理async awite


假如现在有三批任务需要处理,任务数分别为 [9,15,9],任务每次处理需要1秒中

async 关键字 

参考地址

首先,我们使用 async 关键字,把它放在函数声明之前,使其成为 async function。异步函数是一个知道怎样使用 await 关键字调用异步代码的函数。

将 async 关键字加到函数申明中,可以告诉它们返回的是 promise,而不是直接返回值。此外,它避免了同步函数为支持使用 await 带来的任何潜在开销。在函数声明为 async 时,JavaScript引擎会添加必要的处理,以优化你的程序。爽!

每次执行任务函数,函数为异步函数,模拟API异步请求, 耗时大约1秒钟:

我们已经将代码封装在函数中,并且我们在 function 关键字之前包含了 async 关键字。这是必要的 –– 您必须创建一个异步函数来定义一个代码块,在其中运行异步代码; await 只能在异步函数内部工作。

 

JavaScript 全选
// 等待时间
function sleepAsync(delay) {
    return new Promise((resolve) => {
        setTimeout(resolve, delay)
    })
}

async function TaskBody(message) {
    // 等待随机*秒钟
    time = 750 + Math.floor(Math.random() * 500);
    await sleepAsync(time);
    var ts = new Date().format("yyyy-MM-dd hh:mm:ss.S");
    console.log(ts + '| 完成:' + message + '    耗时:' + time)
}

1、同步执行任务

await 异步函数改成同步,函数前需要添加 async 关键字

await关键字:

当 await 关键字与异步函数一起使用时,它的真正优势就变得明显了 —— 事实上, await 只在异步函数里面才起作用。它可以放在任何异步的,基于 promise 的函数之前。它会暂停代码在该行上,直到 promise 完成,然后返回结果值。在暂停的同时,其他正在等待执行的代码就有机会执行了。

您可以在调用任何返回Promise的函数时使用 await,包括Web API函数。

在asyncTest()函数定义中,您可以看到代码与先前的 promise 版本非常相似,但存在一些差异。不需要附加 .then() 代码块到每个promise-based方法的结尾,你只需要在方法调用前添加 await 关键字,然后把结果赋给变量。await 关键字使JavaScript运行时暂停于此行,允许其他代码在此期间执行,直到异步函数调用返回其结果。一旦完成,您的代码将继续从下一行开始执行。例如:

JavaScript 全选
async function asyncTest() {
    console.log('================测试开始')
    // 任务批次 分三批,没批分别执行任务次数 3,15,9
    var dataSource = [3, 15, 9]
    for (var index = 0; index < dataSource.length; index++) {
        // 本批次需要循环执行的任务次数
        count = dataSource[index]
        for (var i = 0; i < count; i++) {
            // 执行任务
            await TaskBody(`任务ID:${index + 1} - ${i + 1}`);
        }
    }
    console.log('================测试结束')
}

这个操作共需要耗时 (3+15+9)*1 = 27 秒

执行结果如下:

Markup 全选
================测试开始
2022-01-21 21:50:50.939| 完成:任务ID:1 - 1    耗时:1056
2022-01-21 21:50:51.820| 完成:任务ID:1 - 2    耗时:878
2022-01-21 21:50:52.872| 完成:任务ID:1 - 3    耗时:1038
2022-01-21 21:50:53.728| 完成:任务ID:2 - 1    耗时:852
2022-01-21 21:50:54.942| 完成:任务ID:2 - 2    耗时:1213
2022-01-21 21:50:55.847| 完成:任务ID:2 - 3    耗时:888
2022-01-21 21:50:57.515| 完成:任务ID:2 - 4    耗时:1045
2022-01-21 21:50:58.319| 完成:任务ID:2 - 5    耗时:777
2022-01-21 21:50:59.565| 完成:任务ID:2 - 6    耗时:1236
2022-01-21 21:51:00.752| 完成:任务ID:2 - 7    耗时:1172
2022-01-21 21:51:01.896| 完成:任务ID:2 - 8    耗时:1117
2022-01-21 21:51:03.41| 完成:任务ID:2 - 9    耗时:1139
2022-01-21 21:51:04.217| 完成:任务ID:2 - 10    耗时:1161
2022-01-21 21:51:05.161| 完成:任务ID:2 - 11    耗时:932
2022-01-21 21:51:06.425| 完成:任务ID:2 - 12    耗时:1249
2022-01-21 21:51:07.462| 完成:任务ID:2 - 13    耗时:1030
2022-01-21 21:51:08.514| 完成:任务ID:2 - 14    耗时:1041
2022-01-21 21:51:09.532| 完成:任务ID:2 - 15    耗时:1010
2022-01-21 21:51:10.529| 完成:任务ID:3 - 1    耗时:988
2022-01-21 21:51:11.299| 完成:任务ID:3 - 2    耗时:761
2022-01-21 21:51:12.298| 完成:任务ID:3 - 3    耗时:990
2022-01-21 21:51:13.365| 完成:任务ID:3 - 4    耗时:1054
2022-01-21 21:51:14.548| 完成:任务ID:3 - 5    耗时:1176
2022-01-21 21:51:15.585| 完成:任务ID:3 - 6    耗时:1035
2022-01-21 21:51:16.620| 完成:任务ID:3 - 7    耗时:1020
2022-01-21 21:51:17.572| 完成:任务ID:3 - 8    耗时:942
2022-01-21 21:51:18.395| 完成:任务ID:3 - 9    耗时:810
================测试结束

2、异步执行

第一步结果我们可以看到这是个耗时的操作,现在我们改造一下,异步调用

C# 全选
function asyncTest() {
    console.log('================测试开始')
    // 任务批次 分三批,没批分别执行任务次数 3,15,9
    var dataSource = [3, 15, 9]
    for (var index = 0; index < dataSource.length; index++) {
        // 本批次需要循环执行的任务次数
        count = dataSource[index]
        for (var i = 0; i < count; i++) {
            // 执行任务
            TaskBody(`任务ID:${index + 1} - ${i + 1}`);
        }
    }
    console.log('================测试结束')
}

执行结果:

Markup 全选
================测试开始
================测试结束
2022-01-21 21:58:41.467| 完成:任务ID:3 - 3    耗时:1116
2022-01-21 21:58:41.467| 完成:任务ID:2 - 15    耗时:1116
2022-01-21 21:58:41.514| 完成:任务ID:2 - 9    耗时:1116
2022-01-21 21:58:41.545| 完成:任务ID:2 - 4    耗时:1116
2022-01-21 21:58:41.546| 完成:任务ID:3 - 6    耗时:1116
2022-01-21 21:58:41.608| 完成:任务ID:2 - 10    耗时:1116
2022-01-21 21:58:41.655| 完成:任务ID:2 - 3    耗时:1116
2022-01-21 21:58:41.655| 完成:任务ID:2 - 11    耗时:1116
2022-01-21 21:58:41.655| 完成:任务ID:3 - 2    耗时:1116
2022-01-21 21:58:41.670| 完成:任务ID:3 - 7    耗时:1116
2022-01-21 21:58:41.671| 完成:任务ID:2 - 6    耗时:1116
2022-01-21 21:58:41.686| 完成:任务ID:3 - 4    耗时:1116
2022-01-21 21:58:41.702| 完成:任务ID:3 - 8    耗时:1116
2022-01-21 21:58:41.732| 完成:任务ID:1 - 2    耗时:1116
2022-01-21 21:58:41.747| 完成:任务ID:2 - 7    耗时:1116
2022-01-21 21:58:41.747| 完成:任务ID:2 - 1    耗时:1116
2022-01-21 21:58:41.747| 完成:任务ID:2 - 5    耗时:1116
2022-01-21 21:58:41.763| 完成:任务ID:2 - 12    耗时:1116
2022-01-21 21:58:41.763| 完成:任务ID:1 - 1    耗时:1116
2022-01-21 21:58:41.794| 完成:任务ID:2 - 13    耗时:1116
2022-01-21 21:58:41.841| 完成:任务ID:3 - 9    耗时:1116
2022-01-21 21:58:41.841| 完成:任务ID:2 - 8    耗时:1116
2022-01-21 21:58:41.841| 完成:任务ID:3 - 5    耗时:1116
2022-01-21 21:58:41.888| 完成:任务ID:2 - 2    耗时:1116
2022-01-21 21:58:41.903| 完成:任务ID:1 - 3    耗时:1116
2022-01-21 21:58:41.918| 完成:任务ID:3 - 1    耗时:1116
2022-01-21 21:58:41.950| 完成:任务ID:2 - 14    耗时:1116

3、等待所有异步任务完成

现在有新需求,要等待所有异步完成后,才输出 测试结束

Promise.all(iterable)

这个方法返回一个新的promise对象,该promise对象在iterable参数对象里所有的promise对象都成功的时候才会触发成功,一旦有任何一个iterable里面的promise对象失败则立即触发该promise对象的失败。这个新的promise对象在触发成功状态以后,会把一个包含iterable里所有promise返回值的数组作为成功回调的返回值,顺序跟iterable的顺序保持一致;如果这个新的promise对象触发了失败状态,它会把iterable里第一个触发失败的promise对象的错误信息作为它的失败错误信息。Promise.all方法常被用于处理多个promise对象的状态集合。参考地址

JavaScript 全选
function asyncTest() {
    console.log('================测试开始')
    // 任务批次 分三批,没批分别执行任务次数 3,15,9
    var dataSource = [3, 15, 9]
    var tks = []
    for (var index = 0; index < dataSource.length; index++) {
        // 本批次需要循环执行的任务次数
        count = dataSource[index]

        for (var i = 0; i < count; i++) {
            // 执行任务
            var tk = TaskBody(`任务ID:${index + 1} - ${i + 1}`);
            tks.push(tk)
        }
    }
    // 等待所有任务都执行完毕
    Promise.all(tks).then(() => {
        console.log('================测试结束')
    });
}

运行结果:

Markup 全选
================测试开始
2022-01-21 22:03:05.976| 完成:任务ID:3 - 7    耗时:1117
2022-01-21 22:03:05.976| 完成:任务ID:2 - 8    耗时:1117
2022-01-21 22:03:05.991| 完成:任务ID:2 - 4    耗时:1117
2022-01-21 22:03:06.53| 完成:任务ID:2 - 3    耗时:1117
2022-01-21 22:03:06.69| 完成:任务ID:3 - 4    耗时:1117
2022-01-21 22:03:06.70| 完成:任务ID:2 - 14    耗时:1117
2022-01-21 22:03:06.85| 完成:任务ID:2 - 12    耗时:1117
2022-01-21 22:03:06.148| 完成:任务ID:3 - 2    耗时:1117
2022-01-21 22:03:06.195| 完成:任务ID:2 - 5    耗时:1117
2022-01-21 22:03:06.226| 完成:任务ID:2 - 6    耗时:1117
2022-01-21 22:03:06.227| 完成:任务ID:1 - 2    耗时:1117
2022-01-21 22:03:06.273| 完成:任务ID:1 - 1    耗时:1117
2022-01-21 22:03:06.274| 完成:任务ID:2 - 2    耗时:1117
2022-01-21 22:03:06.289| 完成:任务ID:3 - 5    耗时:1117
2022-01-21 22:03:06.320| 完成:任务ID:2 - 9    耗时:1117
2022-01-21 22:03:06.321| 完成:任务ID:3 - 9    耗时:1117
2022-01-21 22:03:06.335| 完成:任务ID:3 - 3    耗时:1117
2022-01-21 22:03:06.351| 完成:任务ID:2 - 15    耗时:1117
2022-01-21 22:03:06.352| 完成:任务ID:2 - 11    耗时:1117
2022-01-21 22:03:06.366| 完成:任务ID:2 - 13    耗时:1117
2022-01-21 22:03:06.367| 完成:任务ID:2 - 10    耗时:1117
2022-01-21 22:03:06.381| 完成:任务ID:2 - 7    耗时:1117
2022-01-21 22:03:06.396| 完成:任务ID:2 - 1    耗时:1117
2022-01-21 22:03:06.396| 完成:任务ID:3 - 1    耗时:1117
2022-01-21 22:03:06.412| 完成:任务ID:3 - 8    耗时:1117
2022-01-21 22:03:06.428| 完成:任务ID:3 - 6    耗时:1117
2022-01-21 22:03:06.443| 完成:任务ID:1 - 3    耗时:1117
================测试结束

4、按批次执行异异步任务

有时候,我们执行下一批任务的时候,可能会用到第一批任务的结果,所以需要在执行第二批任务的时候确保第一批任务都已执行完毕

JavaScript 全选
async function asyncTest() {
    console.log('================测试开始')
    // 任务批次 分三批,没批分别执行任务次数 3,15,9
    var dataSource = [3, 15, 9]
    
    for (var index = 0; index < dataSource.length; index++) {
        // 本批次需要循环执行的任务次数
        count = dataSource[index]
        var tks = []
        for (var i = 0; i < count; i++) {
            // 执行任务
            var tk = TaskBody(`任务ID:${index + 1} - ${i + 1}`);
            tks.push(tk)
        }
        // 等待本批次所有任务都执行完毕
        await Promise.all(tks)
    }
    console.log('================测试结束')
}

执行结果:

Markup 全选
================测试开始
2022-01-21 22:06:35.269| 完成:任务ID:1 - 3    耗时:903
2022-01-21 22:06:35.316| 完成:任务ID:1 - 2    耗时:903
2022-01-21 22:06:35.317| 完成:任务ID:1 - 1    耗时:903
2022-01-21 22:06:36.192| 完成:任务ID:2 - 15    耗时:860
2022-01-21 22:06:36.250| 完成:任务ID:2 - 5    耗时:860
2022-01-21 22:06:36.266| 完成:任务ID:2 - 8    耗时:860
2022-01-21 22:06:36.329| 完成:任务ID:2 - 1    耗时:860
2022-01-21 22:06:36.345| 完成:任务ID:2 - 4    耗时:860
2022-01-21 22:06:36.392| 完成:任务ID:2 - 10    耗时:860
2022-01-21 22:06:36.454| 完成:任务ID:2 - 7    耗时:860
2022-01-21 22:06:36.454| 完成:任务ID:2 - 13    耗时:860
2022-01-21 22:06:36.500| 完成:任务ID:2 - 2    耗时:860
2022-01-21 22:06:36.516| 完成:任务ID:2 - 3    耗时:860
2022-01-21 22:06:36.531| 完成:任务ID:2 - 11    耗时:860
2022-01-21 22:06:36.531| 完成:任务ID:2 - 12    耗时:860
2022-01-21 22:06:36.531| 完成:任务ID:2 - 6    耗时:860
2022-01-21 22:06:36.561| 完成:任务ID:2 - 14    耗时:860
2022-01-21 22:06:36.577| 完成:任务ID:2 - 9    耗时:860
2022-01-21 22:06:37.382| 完成:任务ID:3 - 8    耗时:1038
2022-01-21 22:06:37.470| 完成:任务ID:3 - 7    耗时:1038
2022-01-21 22:06:37.495| 完成:任务ID:3 - 5    耗时:1038
2022-01-21 22:06:37.496| 完成:任务ID:3 - 3    耗时:1038
2022-01-21 22:06:37.587| 完成:任务ID:3 - 4    耗时:1038
2022-01-21 22:06:37.618| 完成:任务ID:3 - 9    耗时:1038
2022-01-21 22:06:37.664| 完成:任务ID:3 - 6    耗时:1038
2022-01-21 22:06:37.664| 完成:任务ID:3 - 1    耗时:1038
2022-01-21 22:06:37.758| 完成:任务ID:3 - 2    耗时:1038
================测试结束

 

版权声明:本文为YES开发框架网发布内容,转载请附上原文出处连接
管理员
上一篇:从数据库或者其他位置加载ASP.NET MVC Views 视图 数据库中加载 cshtml
下一篇:Javascript JS日期格式化显示
评论列表

发表评论

评论内容
昵称:
验证码:
验证码
关联文章

例子介绍JavaScript异步处理async awite
vue中异步函数async和await的
Javascript 中通过 yield 和 promise 使异步变同步
async & await 的前世今生
Task 使用详细[基础操作,异步原则,异步函数,异步模式]
.net异步Task转同步
.Net Core——SignalR撸游戏
C# XML 序列与反序列详解及实战示例
C# 从做早餐看同步异步
WPF 布局 在有限空间内让两元素尽可能撑开的例子
HttpContext.Current:异步模式下的疑似陷阱之源
SQL Server中常全局变量介绍
EF并发处理,防止并发修改数据
正则表达式,通俗易懂的介绍
C#图片处理
Zookeeper 可视管理工具
.Net Minimal API 介绍
使用 .NET Core 和 Quartz.NET 实现任务调度持久:更相信配置任务调度
Winform开发的快速、健壮、解耦的点建议
话说C#程序员人手一ORM

热门标签
.NET Core .NET Reactor ag-grid AI发布 api安全 ASP.NET Core C#DLL加密 C#播放声音 C#代码混淆 C#代码加密 ChromeDriver Codex DateTime DBeaver devexpress devTool DLL混淆 edge.js EF EFCore Electron element-ui el-form el-table excel FastReport FileStream FolderBrowerDialog FolderSelectDialog form提交 git gridcontrol gridview input javascript json字符串 JS转换对象JSON jwt JWT授权 linq log Math MCP mitmproxy MVC MySQL Navicat netstat nginx node_modules NSwag Nuget Nuget镜像 number PowerShell pyinstaller python pythoncom python爬虫 python抓包 pywin32 redis Requests-html RestSharp Selenium sql SQL Server Swagger to-cms Visual Studio VSCode vue VueRouter vue路由 VUE页面通讯 Webpack Windows Windows服务 winform wmi xlrd yaml YESCMS YESWEB开发框架 白象 表单提交 播放声音 打开URL 代码混淆 弹窗提醒 端口占用 对象转换 分布式 公共字典 机器码 进程排查 静态资源 开发指南 路由参数 密钥 配置教程 配置文件 权限 人工智能 任务 任务调度 日期间隔 日志 日志记录 省市区 授权验证 数据库 四舍五入 文案 文件读取 文件夹选择 文件目录选择 问题排查 行政区域数据 页面通讯 中间件 CSharp 事务锁 工单系统 并发控制 重复提交 CMS Markdig Markdown markdown-it marked 技术选型 VS Code 开发工具 源代码管理 版本控制 Docker PostgreSQL 时区 部署排查 CMS架构 EF Core 主题系统 二次开发 插件系统 容器 运维命令 镜像清理 Linux NAS 远程挂载 飞牛 fnOS S/4HANA SAP GUI SAP HANA SAP R/3 SAP入门 SAP版本 ERP SAP SAP MM 库存管理 物料管理 采购管理 入门教程 SAP S/4HANA SPRO 企业结构 采购组织 MM01 物料主数据 物料类型 BP分组 业务伙伴 供应商主数据 ME41 RFQ 库存物料 采购流程 ME51 消耗性物料 科目分配 采购申请 AC03 ML81N 外部服务 服务主数据 Business Partner SAP培训 ME51N MM模块 Lean Services MM-SRV 外部服务采购 PIR 供应来源 采购主数据 采购信息记录 ME31K 框架协议 计划协议 采购合同 ME01 供应来源确定 货源清单 MEQ1 供应源确定 配额安排 配额评分 MD04 MD21 MRP 计划文件 需求计划 批量程序 MD01N MD02 MRP Live MD05 MM 物料计划 优化采购 供应源 采购订单
联系我们
联系电话:15090125178(微信同号)
电子邮箱:garson_zhang@163.com
站长微信二维码
微信二维码