化繁为简,用几个例子介绍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# 从做早餐看同步异步
WPF 布局 在有限空间内让两元素尽可能撑开的例子
HttpContext.Current:异步模式下的疑似陷阱之源
EF并发处理,防止并发修改数据
SQL Server中常全局变量介绍
C#图片处理
正则表达式,通俗易懂的介绍
C# MEF插件开发
JQuery将form表单转换json,并提交后台处理
.Net Minimal API 介绍
System.Web.HttpContext.Current
Winform开发的快速、健壮、解耦的点建议
话说C#程序员人手一ORM

联系我们
联系电话:15090125178(微信同号)
电子邮箱:garson_zhang@163.com
站长微信二维码
微信二维码