集千篇理论精华,感悟对同步和异步的理解
一、promise本身是同步还是异步呢?
众所周知,Promise是ES6提出的解决异步编程导致陷入回调地狱问题的,那么Promise是同步的还是异步的?可以确定的是,Promise本身是同步的,而他的.then和.catch为异步的。 举个栗子: console.log(1) let a = new Promise((res,rej) => { console.log(2); }); console.log(3); let b = new Promise((res,rej) => { console.log(4); }); console.log(5); //1,2,3,4,5
二、返回的异步代码执行顺序 (.then / .catah)
console.log(1) let a = new Promise((res,rej) => { console.log(2); res(); }); console.log(3); let b = new Promise((res,rej) => { console.log(4); res(); }); console.log(5); a.then(() => { //先执行a,是因为.then是一个微任务,而且a最先进入微任务队列,所以现在执行a,在执行b,但都必须是在等到同步代码结束之后在进入执行队列; console.log(6) }) b.then(() => { console.log(7) })
栗子:
promise1
promise2
1
4
2
5
3
6
三、宏任务与微任务
- JS是一种单线程语言,代码执行顺序(同步代码先执行---->等同步代码执行完毕异步代码在执行)主线任务清空之后,异步进入任务队列,开始从任务队列进入到主线程。 - 异步任务里面又存在宏任务和微任务。(同步代码不存在宏任务与微任务一说) - 宏任务:定时器 / **script**。 - 微任务:.then
<script> console.log('start'); //同步 setTimeout(()=>{ //宏任务 console.log('time1'); }) new Promise((resolve)=>{ console.log('promise'); //同步 resolve(); }) .then(()=>{ //.then是异步 微任务 console.log('then'); }) setTimeout(()=>{ // 宏任务 console.log('time2'); }) console.log('外部console'); //同步 </script> 执行顺序: 1、首先同步代码先依次执行; star,promise 外部console 2、then,第一个宏任务下的微任务, 3、time1 time2 宏任务
注意:在下一个宏任务开始之前,必须将当前主线微任务全部执行完毕,才进入下一个宏任务,也就是所谓的事件循环---eventloop。
三、async和await函数
async 函数是什么?一句话,它就是 Generator 函数的语法糖,async函数就是将 Generator 函数的星号(*)替换成async,将yield替换成await,仅此而已。
async
函数的返回值是 Promise 对象,这比 Generator 函数的返回值是 Iterator 对象方便多了。你可以用then
方法指定下一步的操作。
进一步说,async
函数完全可以看作多个异步操作,包装成的一个 Promise 对象,而await
命令就是内部then
命令的语法糖。
注意,await之后的代码必须等await语句执行完成后(包括微任务完成),才能执行后面的,也就是说,只有运行完await语句,才把await语句后面的全部代码加入到微任务行列,
所以,在遇到await promise时,必须等await promise函数执行完毕才能对await语句后面的全部代码加入到微任务中,所以, 在等待await Promise.then微任务时, 1.运行其他同步代码, 2.等到同步代码运行完,开始运行await promise.then微任务, 3.await promise.then微任务完成后,把await语句后面的全部代码加入到微任务行列, 4.根据微任务队列,先进后出执行微任
console.log(1) async function async1(){ console.log('async1 start') await async2() //在此先做返回,将后面所有的代码放到异步队列, console.log('async1 end') } async function async2(){ console.log('async2') } async1(); console.log('i am koala')
//结果:
1
async1 start
async2
i am koala
async1 end
async 函数返回一个 Promise 对象,(promise 本身为同步代码)
async function t1() { console.log(1) console.log(2) await new Promise(resolve => { setTimeout(() => { console.log('t1p') resolve() }, 5000) }) await console.log(3) console.log(4) } async function t2() { console.log(5) console.log(6) await Promise.resolve().then(() => console.log('t2p')) console.log(7) console.log(8) } t1() t2() console.log('end')
1
2
5
6
end
t2p
7
8
t1p
3
4
async function async1() { console.log( 'async1 start' ) await async2() console.log( 'async1 end' ) } async function async2() { console.log( 'async2' ) } console.log( 'script start' ) //属于一个同步代码,优先于async返回的promise执行,在async内部! setTimeout( function () { console.log( 'setTimeout' ) }, 0 ) async1(); new Promise( function ( resolve ) { console.log( 'promise1' ) resolve(); } ).then( function () { console.log( 'promise2' ) } ) console.log( 'script end' )
//执行结果
script start
async1 start
async2
promise1
script end
promise2
async1 end
setTimeout
async function t1 () { console.log(1) //1 console.log(2) //2 new Promise( function ( resolve ) { console.log( 'promise3' ) //3 resolve(); } ).then( function () { console.log( 'promise4' ) } ) await new Promise( function ( resolve ) { //如果它等到的是一个 promise 对象,await 也会暂停async后面的代码,先执行async外面的同步代码, //等着 Promise 对象 fulfilled,然后把 resolve 的参数作为 await 表达式的运算结果 console.log( 'b' ) //4 resolve(); } ).then( function () { console.log( 't1p' ) } ) console.log(3) console.log(4) new Promise( function ( resolve ) { console.log( 'promise5' ) resolve(); } ).then( function () { console.log( 'promise6' ) } ) } setTimeout( function () { console.log( 'setTimeout' ) }, 0 ) async function t2() { console.log(5) console.log(6) await Promise.resolve().then(() => console.log('t2p')) //属于promise方法,不是对象! console.log(7) console.log(8) } t1() new Promise( function ( resolve ) { console.log( 'promise1' ) //同步代码 resolve(); } ).then( function () { console.log( 'promise2' ) } ) t2() console.log('end');
//执行结果;
1
2
promise3
b
promise1
5
6
end
promise4
t1p
promise2
t2p
3
4
promise5
7
8
promise6
setTimeout
分析:
当遇见第一个await之后,阻止后面的承誉德执行,加入微任务队列;执行其他同步代码,但是5,6先于end之前执行,是因为t2在end之前调用。
总结:
await后面如果等到的是promise对象,执行完resolve之后,阻止后面程序的运行,加入微任务队列,
如果是promise方法,也就是不是promise对象的时候,同样也阻止后面的程序的运行,也加入微任务队列。
要有最平凡的生活,和最遥远的梦想,即使明天天寒地冻,路遥马亡……
原文地址:https://www.cnblogs.com/gzw-23/p/11802303.html
- JSP Session管理
- 明年4月1日起扫码付款将限额 最低单日限额500元
- 支付宝、微信支付即将限额?这让出门不带钱包的我怎么过!
- 王者荣耀玩家的福音 区块链技术可以让游戏资产变成真实资产
- 不知道这些的IT人可能白过了2017!
- 什么情况?又出新规定,微信支付和支付宝支付居然要被限额了?
- 三十分钟掌握STL
- 谷歌AI新升级,装备审美功能给照片评分
- 【设计模式】—— 适配器模式Adapter
- 【设计模式】—— 单例模式Singleton
- 【Spring实战】—— 3 使用facotry-method创建单例Bean总结
- JS面向对象高级特性
- 图解闭包
- 【web必知必会】——图解HTTP(上)
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- String - 71. Simplify Path
- 性能测试工具——wrk
- String - 67. Add Binary
- Math - 50. Pow(x, n)
- String - 44. Wildcard Matching
- DFS&BFS - 37. Sudoku Solver
- Array - 36. Valid Sudoku
- Array - 57. Insert Interval
- Binary Search - 378. Kth Smallest Element in a Sorted Matrix
- Array - 59. Spiral Matrix II
- Array - 54. Spiral Matrix
- String - 8. String to Integer (atoi)
- Array - 16. 3Sum Closest
- Array - 15. 3Sum
- Design - 146. LRU Cache