async和await是如何实现异步编程?

简介:

async和await是如何实现异步编程?
目录

异步编程样例
样例解析
浅谈Promise如何实现异步执行
参考

1.异步编程样例

样例:

// 等待执行函数
function sleep(timeout) {
return new Promise((resolve) => {

setTimeout(resolve, timeout)

})
}

// 异步函数
async function test() {
console.log('test start')
await sleep(1000)
console.log('test end')
}

console.log('start')
test()
console.log('end')
执行结果:

start
test start
end
test end

2.样例解析

在样例代码中,test异步函数使用了async和await语法,这是ES2017里面的异步编程规范。而为了在较低版本的浏览器或Node支持这种语法,其中一种解决方案是将其转化为Generator函数和Promise来实现。换句话说,任何的async和await实现的异步函数,都可以替换成Generator函数和Promise实现。

第一步:先将async和await语法替换为相应的Generator 函数,如下

// 代码结构完全一致,只是替换了对应关键字
function *test() {
console.log('test start')
yield sleep(1000)
console.log('test end')
}
第二步:为了执行Generator 函数,使用Promise实现一个自动执行器函数 spawn

function spawn(genF) {
return new Promise(function(resolve, reject) {

const gen = genF();
function step(nextF) {
  let next;
  try {
    next = nextF();
  } catch(e) {
    return reject(e);
  }
  if(next.done) {
    return resolve(next.value);
  }
  Promise.resolve(next.value).then(function(v) {
    step(function() { return gen.next(v); });
  }, function(e) {
    step(function() { return gen.throw(e); });
  });
}
step(function() { return gen.next(undefined); });

});
}
第三步:将相应的Generator 函数和自动执行器函数相结合,即可得最终的等价代码

function asyncTest() {
spawn(test)
}

console.log('start')
asyncTest()
console.log('end')
第四步:执行结果,与原来的一致

start
test start
end
test end
第五步:分析asyncTest函数执行过程

执行到 spawn(test),进入spawn函数中,创建一个Promise并返回。
执行到const gen = genF(),获取一个状态机。(Generator 函数是一个状态机,封装了多个内部状态。)
执行到 step(function() { return gen.next(undefined); }), 进入step 函数中。
执行到next = nextF() ,next等于gen.next(undefined)的返回结果。
当gen.next(undefined)开始执行,状态机第一次调用,直到遇到第一个yield表达式为止,即yield sleep(1000),此时控制台先输出"test start",并且返回第一个状态{ value: reuslt, done: false }, 而 reuslt等于sleep(1000)返回的结果,其是一个Promise。
执行到if(next.done) ,此时第一个状态的done为false,所以不执行if语句里面,继续往下执行。
执行到Promise.resolve(next.value),由于第一个状态的value是一个Promise,所以直接返回其本身,也就相当于执行sleep(1000).then(...),sleep函数异步等待1秒后,resolve接受的值为undefined,继续执行then方法。
执行到 step(function() { return gen.next(v); }),此时v为undefined,再次进入step 函数中。
再次执行到next = nextF() ,next等于gen.next(undefined)的返回结果。
当gen.next(undefined)再次执行时,状态机第二次调用,此时Generator函数已经执行完毕,此时控制台先输出"test end",并且返回最后的状态{ value: undefined, done: true }
执行到if(next.done) ,此时第一个状态的done为true,所以执行if语句里面。
执行到return resolve(next.value),此时最初的Promise成功执行。
至此asyncTest函数执行结束。

3.浅谈Promise如何实现异步执行

从上述样例解析中可以看出,我们是用Promise来实现代码的异步执行,那Promise的内部是如何实现异步执行的呢?

通过查看Promise的源码实现,发现其异步执行是通过asap这个库来实现的。

asap是as soon as possible的简称,在Node和浏览器环境下,能将回调函数以高优先级任务来执行(下一个事件循环之前),即把任务放在微任务队列中执行。

宏任务(macro-task)和微任务(micro-task)表示异步任务的两种分类。在挂起任务时,JS 引擎会将所有任务按照类别分到这两个队列中,首先在 macrotask 的队列(这个队列也被叫做 task queue)中取出第一个任务,执行完毕后取出 microtask 队列中的所有任务顺序执行;之后再取 macrotask 任务,周而复始,直至两个队列的任务都取完。

用法:

asap(function () {

// ...

});

4.参考

ECMAScript 6 入门 - async 函数

【翻译】Promises/A+规范

Promise - Bare bones Promises/A+ implementation

原文地址https://www.cnblogs.com/forcheng/p/12668387.html

相关文章
|
定位技术 开发工具 Android开发
Leaflet开发入门
Leaflet开发入门
599 0
|
10月前
|
机器学习/深度学习 人工智能 自然语言处理
自监督学习:引领机器学习的新革命
自监督学习的思想可以追溯到几年前,最早是在图像处理领域被提出。随着深度学习的快速发展,研究者们逐渐认识到未标注数据的巨大潜力。尤其是在大规模数据集的爆炸式增长下,获取标注数据的成本越来越高,而利用自监督学习的方法来减少对标注数据的依赖变得越来越重要。
|
9月前
|
前端开发 JavaScript API
前端大佬都在用的usePagination究竟有多强?
usePagination 是 alovajs 提供的一款强大的分页请求工具,专为简化分页场景而生。它能自动管理分页数据、支持预加载、追加模式以及丰富的列表操作函数,极大提升开发效率与用户体验。作为下一代请求工具,alovajs 不仅涵盖 15+ 请求策略,还通过状态化数据和特定事件减少代码量。无论是下拉加载还是翻页优化,usePagination 都能轻松应对。如果你正在寻找高效的分页解决方案,不妨试试这个贴心的工具!
|
敏捷开发 数据可视化 项目管理
2024年最强的5大需求管理工具有哪些?如何选择最适合的需求管理软件?
随着项目管理和产品开发复杂性的增加,需求管理成为团队成功的关键。本文推荐5款需求管理工具:板栗看板、ProdPad、Craft.io、Airfocus和Targetprocess,分别适用于任务分配、产品规划、需求捕捉、优先级管理和敏捷开发等场景,帮助团队提高协作效率和交付质量。
 2024年最强的5大需求管理工具有哪些?如何选择最适合的需求管理软件?
|
供应链 监控 数据可视化
物联网技术在物流与供应链管理中的应用与挑战
本文探讨了物联网技术在物流与供应链管理中的应用,通过实时追踪、信息共享、智能化决策等手段,大幅提升了管理效率和智能化水平。特别介绍了板栗看板作为专业可视化工具,在数据监控、分析及协同作业中的重要作用。未来,随着技术的进一步发展,物流与供应链管理将更加智能高效,但也面临数据安全、标准化等挑战。
1028 2
|
人工智能 数据可视化 TensorFlow
从Tensorflow模型文件中解析并显示网络结构图(CKPT模型篇)
从Tensorflow模型文件中解析并显示网络结构图(CKPT模型篇)
从Tensorflow模型文件中解析并显示网络结构图(CKPT模型篇)
|
存储 缓存 分布式计算
阿里云服务器2核8G、4核32G、8核64G配置最新收费标准和活动价格参考
2核8G、4核32G、8核64G配置的云服务器处理器与内存比为1:8,这种配比的云服务器一般适用于数据分析与挖掘,Hadoop、Spark集群和数据库,缓存等内存密集型场景,因此,多为企业级用户选择,目前用户购买2核16G配置活动价格最低为2439.24元/1年起,购买4核32G配置活动价格最低为4499.88元/1年起,购买8核64G配置活动价格最低为8621.16元/1年起,本文介绍这些配置的最新购买价格,包含原价收费标准和最新活动价格。
829 0
阿里云服务器2核8G、4核32G、8核64G配置最新收费标准和活动价格参考
|
JSON API 数据格式
京东API接口解析,实现按关键字搜索商品
京东API接口解析,实现按关键字搜索商品
811 0
|
.NET C# 开发框架
【技术贴】c# asp.net 无法直接启动带有“类库输出类型”的项目 若要调试此项目,请在此解决方
c# asp.net 无法直接启动带有“类库输出类型”的项目 若要调试此项目,请在此解决方案中添加一个引用库项目的可执行项目。将这个可执行项目设置为启动项     解决办法: 右键解决方案->属性->通用属性->启动项目->单启动项目->选择Web项目
2549 0