promise、async、await、settimeout异步原理与执行顺序
一道经典的前端笔试题,你能一眼写出他们的执行结果吗?
async function async1() {
console.log("async1 start");
await async2();
console.log("async1 end"); }
async function async2() {
console.log( 'async2');
}
console.log("script start");
setTimeout(function () {
console.log("settimeout");
},0);
async1();
new Promise(function (resolve) {
console.log("promise1");
resolve();
}).then(function () {
console.log("promise2");
});
console.log('script end');
首先第一个问题: JavaScript运行机制是什么?
详细可参考:https://baijiahao.baidu.com/s?id=1615713540466951098&wfr=spider&for=pc
总结几点就是:
- JavaScript语言是单线程的,同一个时间只能做一件事;
- 遵循事件循环机制,当JS解析执行时,会被引擎分为两类任务,同步任务(synchronous) 和 异步任务(asynchronous)。对于同步任务来说,会被推到执行栈按顺序去执行这些任务。对于异步任务来说,当其可以被执行时,会被放到一个 任务队列(task queue) 里等待JS引擎去执行。当执行栈中的所有同步任务完成后,JS引擎才会去任务队列里查看是否有任务存在,并将任务放到执行栈中去执行,执行完了又会去任务队列里查看是否有已经可以执行的任务。这种循环检查的机制,就叫做事件循环(Event Loop)。对于任务队列,其实是有更细的分类。其被分为 微任务(microtask)队列 & 宏任务(macrotask)队列。
第二个问题:Promise的原理和运行机制是什么?
古人云:“君子一诺千金”,这种“承诺将来会执行”的对象在JavaScript中称为Promise对象。
Promise 是异步编程的一种解决方案,其实是一个构造函数,自己身上有all、reject、resolve这几个方法,原型上有then、catch等方法。
参考:https://blog.csdn.net/qq_37860963/article/details/81539118
这里扩展一个问题:什么是异步呢?
同步
就是一件事一件事的执行。只有前一个任务执行完毕,才能执行后一个任务。
js代码只能一行一行的执行,不能在同一时间执行多个js代码任务,这就导致如果有一段耗时较长的计算,或者是一个ajax请求等IO操作,如果没有异步的存在,就会出现用户长时间等待,并且由于当前任务还未完成,所以这时候所有的其他操作都会无响应,这时候就需要异步任务。
参考:https://blog.csdn.net/li123128/article/details/80650256
Promise运行顺序总结:
- promise的构造函数是同步执行,promise.then中的函数是异步执行。
- 构造函数中的 resolve 或 reject 只有第一次执行有效,多次调用没有任何作用。promise状态一旦改变则不能再变。
- promise 的 .then 或者 .catch 可以被调用多次,但这里 Promise 构造函数只执行一次。或者说 promise 内部状态一经改变,并且有了一个值,那么后续每次调用 .then 或者 .catch 都会直接拿到该值。
- 如果在一个then()中没有返回一个新的promise,则 return 什么下一个then就接受什么,如果then中没有return,则默认return的是 undefined.
- then()的嵌套会先将内部的then()执行完毕再继续执行外部的then();
- catch和then的连用,如果每一步都有可能出现错误,那么就可能出现catch后面接上then的情况。如果在catch中也抛出了错误,则后面的then的第一个函数不会执行,因为返回的 promise状态已经为rejected了
第三个问题:async、await执行顺序?
什么是Async/Await?
- async/await是写异步代码的新方式,以前的方法有回调函数和Promise。
- async/await是基于Promise实现的,它不能用于普通的回调函数。
- async/await与Promise一样,是非阻塞的。
- async/await使得异步代码看起来像同步代码,这正是它的魔力所在。
- await关键字只能用在aync定义的函数内。async函数会隐式地返回一个promise,该promise的reosolve值就是函数return的值。
执行顺序:
使用 async 定义的函数,当它被调用时,它返回的其实是一个 Promise 对象。(当这个 async 函数返回一个值时,Promise 的 resolve 方法会负责传递这个值;当 async 函数抛出异常时,Promise 的 reject 方法也会传递这个异常值。)
await是一个让出线程的标志。await后面的函数会先执行一遍,然后就会跳出整个async函数来执行后面js栈的代码,等本轮事件循环执行完了之后又会跳回到async函数中等待await后面表达式的返回值,如果返回值为非promise则继续执行async函数后面的代码,否则将返回的promise放入promise队列。
参考:https://segmentfault.com/a/1190000011296839
问题四:setTimeout的执行?
setTimeout和Promise一样也是异步的
宏任务一般包括:整体代码script,setTimeout,setInterval。
微任务:Promise,process.nextTick
微任务执行优先级高于宏任务,所以Promise比setTimeout优先执行。
理解了以上4个问题,那么这道笔试题也就容易理解了
最终结果:
promise、async、await、settimeout异步原理与执行顺序的更多相关文章
- Atitit. Async await 优缺点 异步编程的原理and实现 java c# php
Atitit. Async await 优缺点 异步编程的原理and实现 java c# php 1. async & await的来源1 2. 异步编程history1 2.1. 线程池 2 ...
- promise async await使用
1.Promise (名字含义:promise为承诺,表示其他手段无法改变) Promise 对象代表一个异步操作,其不受外界影响,有三种状态: Pending(进行中.未完成的) Resolved( ...
- async+await处理异步问题
在编写网页的时候我们常常会遇到异步问题,async+await是es6提出的解决异步的方法,下面我们来看看这个方法怎么实现解决异步的, 大家都知道,setTimeout是一个定时器.他是一个异步执行的 ...
- [转] js async await 终极异步解决方案
阅读目录 回顾 Promise async await 字面理解 async.await 如何执行 await 操作符 总结 既然有了promise 为什么还要有async await ? 当然是pr ...
- [.NET] 利用 async & await 的异步编程
利用 async & await 的异步编程 [博主]反骨仔 [出处]http://www.cnblogs.com/liqingwen/p/5922573.html 目录 异步编程的简介 异 ...
- [.NET] 利用 async & await 进行异步 IO 操作
利用 async & await 进行异步 IO 操作 [博主]反骨仔 [出处]http://www.cnblogs.com/liqingwen/p/6082673.html 序 上次,博主 ...
- 使用ES6新特性async await进行异步处理
我们往往在项目中会遇到这样的业务需求,就是首先先进行一个ajax请求,然后再进行下一个ajax请求,而下一个请求需要使用上一个请求得到的数据,请求少了还好说,如果多了,就要一层一层的嵌套,就好像有点c ...
- vue使用技巧:Promise + async + await 解决组件间串行编程问题
业务场景描述 大家都通过互联网投递过简历,比如在智联.58.猎聘等平台.投递心仪的职位前一般都需要前提创建一份简历,简历编辑界面常规的布局最上面是用户的个人基本信息,如姓名.性别.年龄.名族等,接着是 ...
- 深入理解协程(三):async/await实现异步协程
原创不易,转载请联系作者 深入理解协程分为三部分进行讲解: 协程的引入 yield from实现异步协程 async/await实现异步协程 本篇为深入理解协程系列文章的最后一篇. 从本篇你将了解到: ...
随机推荐
- 力扣——Next Permutation(下一个排列) python实现
题目描述: 中文: 实现获取下一个排列的函数,算法需要将给定数字序列重新排列成字典序中下一个更大的排列. 如果不存在下一个更大的排列,则将数字重新排列成最小的排列(即升序排列). 必须原地修改,只允许 ...
- 转帖 移动前端开发之viewport的深入理解
在移动设备上进行网页的重构或开发,首先得搞明白的就是移动设备上的viewport了,只有明白了viewport的概念以及弄清楚了跟viewport有关的meta标签的使用,才能更好地让我们的网页适配或 ...
- 转 Tomcat访问日志详细配置
配置http访问日志.Tomcat自带的能够记录的http访问日志已经很详细了取消下面这段的注释: <Valve className="org.apache.catalina.valv ...
- c++后台开发面试常见知识点总结(四)数据库
数据库的索引类型 聚集索引和非聚集索引的区别(叶节点存储内容) 唯一性索引和主码索引的区别 索引的优缺点,什么时候使用索引,什么时候不能使用索引(重点) 索引最左前缀问题 数据库中事务的ACID 数据 ...
- 理解Java主函数中的"String[] args"
public class Understand_String_args { public static void main(String[] args) { System.out.printf(&qu ...
- ThreadLocal内存泄漏
原创转载请注明出处:https://www.cnblogs.com/agilestyle/p/11421437.html 内存泄漏 内存泄漏是指不再使⽤的对象⽆法得到及时的回收,持续占⽤内存空间,从⽽ ...
- c++使用不定参数
定义不定参数,使用的宏有: va_start(ap, arg) 初始化一个va_list的变量ap va_arg(ap, type) 获取下一个type类型的参数 va_end(ap) 结束使用 ...
- yum工具入门
一yum介绍 注意学完了yum之后,rpm的使用频率就少了.有些功能yum用起来不如rpm更方便. CentOS: yum, dnfYUM: Yellowdog Update Modifier,rpm ...
- php ceil()函数 语法
php ceil()函数 语法 ceil()函数怎么用? php ceil()函数的作用是向上舍入为最接近的整数,语法是ceil(number),表示返回不小于参数X的下一个整数,如果没有小数,返回参 ...
- thinkphp5 图片上传七牛云
<?php namespace app\cxc\controller; use Qiniu\Auth; use Qiniu\Storage\UploadManager; use think\Co ...