1.同步和异步是什么:

​ ①同步:同步是指如果一个进程在执行某个请求的时候,如果该请求需要等待一段时间,那么该进程会一直等待下去,直到收到返回信息才继续执行下去

​ ②异步: 指一个请求在执行某个请求的时候,即使该请求需要等待一段时间,该请求也不会阻塞下面的请求,而是一直执行下去

2.异步函数发展史

​ callback --> generator --> promise和then -->async和await

3.常见的异步方式:

​ ①定时器 // setTimeout(fn,time) 、setInterval(fn,time)

​ ②接口调用 //ajax

​ ③事件函数 //事件监听事件

4.多次异步调用的结果:

​ ①多次异步调用的结果会导致顺序可能不同步

​ ②异步调用的结果如果存在依赖,则需要嵌套。当进行多次回调函数时,会出现回调地狱

5.Promise的概述:

​ ①背景:JavaScript是单线程的,当执行一个请求,如果该请求的请求时间过长,该应用就会变得卡顿,那么让代码异步执行就变得很有必要了。

​ ②介绍:

​ 1. Promise是一个构造函数,接受一个参数作为对象,该函数的两个参数分别是 resolve和reject 。

​ 2.Promise身上有all、reject、resolve这几个眼熟的方法,原型上有then、catch等同样很眼熟的方法。

​ 3.promise有三种状态,pending、fulfilled、rejected,状态改变只能是pending->fulfilled或者 pending->rejected , 状态一旦改变则不能再变。(要想改变得用return返回一个异步函数)

​ ③作用:

​ 1.解决回调地狱的问题

​ 2.链式调用

6.Promise的注意事项:

   var p = new Promise(function(resolve, reject){
//做一些异步操作
setTimeout(function(){
console.log('异步任务执行完成');
resolve('随便什么数据2');
}, 2000);
});

​ 运行代码,会在2秒后输出“异步任务执行完成”。注意!我只是new了一个对象,并没有调用它,我们传进去的函数就已经执行了,这是需要注意的一个细节。所以我们用Promise的时候一般是包在一个函数中,在需要的时候去运行这个函数,如:

function runAsync(){
var p = new Promise(function(resolve, reject){
//做一些异步操作
setTimeout(function(){
console.log('执行完成');
resolve('随便什么数据');
}, 2000);
});
return p;
}
runAsync()

7.Promise的基本用法:

​ (1)使用new实例化一个Promise对象,Promise的构造函数中传递一个参数。这个参数是一个函数,该函数用于处理异步任务。

​ (2)并且传入两个参数:resolve和reject,分别表示异步执行成功后的回调函数和异步执行失败后的回调函数;

​ (3)通过 promise.then() 处理返回结果。这里的 p 指的是 Promise实例。

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<script>
function getAsync(){
const promise = new Promise((resolve, reject) => {
// 这里做异步任务(比如ajax 请求接口。这里暂时用定时器代替)
setTimeout(function() {
// 接口返回的数据
var data = { retCode: 0, msg: 'qianguyihao' };
if (data.retCode == 0) {
// 接口请求成功时调用
resolve(data);
} else {
// 接口请求失败时调用
reject({ retCode: -1, msg: 'network error' });
}
}, 100);
});
return promise
}
// 第二步:业务层的接口调用。这里的 data 就是 从 resolve 和 reject 传过来的,也就是从接口拿到的数据
getAsync().then(data => {
// 从 resolve 获取正常结果
console.log(data);
}).catch(data => {
// 从 reject 获取异常结果
console.log(data);
});
</script>
</body>
</html>

8.Promise的链式用法

​ 解释:链式用法就是当一个异步执行完毕再执行另外一个异步

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<script>
function getAsync(param){
const promise = new Promise((resolve, reject) => {
// 这里做异步任务(比如ajax 请求接口。这里暂时用定时器代替)
setTimeout(function() {
// 接口返回的数据
var data = { retCode: 0, msg: 'qianguyihao' };
if (data.retCode == 0) {
// 接口请求成功时调用
resolve(data);
console.log(param);
} else {
// 接口请求失败时调用
reject({ retCode: -1, msg: 'network error' });
}
}, 1000);
});
return promise
} // 第二步:业务层的接口调用。这里的 data 就是 从 resolve 和 reject 传过来的,也就是从接口拿到的数据
getAsync("1").then(data => {
// 从 resolve 获取正常结果
return getAsync("2")
}).then(data => {
// 从 resolve 获取正常结果
return getAsync("3")
})
</script>
</body>
</html>

9.promise链式用法的缺点:

​ 对于不熟悉promise的人来说,简直就是噩梦,因此才出了这一篇博文,有不足之处望提出,会加以改进

10.Promise的常用api

​ 1.Promise.all():并发处理多个异步任务,所有任务都执行成功,才能得到结果。

​ 2.Promise.race(): 并发处理多个异步任务,只要有一个任务执行成功,就能得到结果。

###Promise.all()
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<script type="text/javascript">
/*
封装 Promise 接口调用
*/
function queryData(url) {
return new Promise((resolve, reject) => {
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if (xhr.readyState != 4) return;
if (xhr.readyState == 4 && xhr.status == 200) {
// 处理正常结果
resolve(xhr.responseText);
} else {
// 处理异常结果
reject('服务器错误');
}
};
xhr.open('get', url);
xhr.send(null);
});
} var promise1 = queryData('http://localhost:3000/a1');
var promise2 = queryData('http://localhost:3000/a2');
var promise3 = queryData('http://localhost:3000/a3'); Promise.all([promise1, promise2, promise3]).then(result => {
console.log(result);
});
</script>
</body>
</html>
###Promise.race
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<script type="text/javascript">
/*
封装 Promise 接口调用
*/
function queryData(url) {
return new Promise((resolve, reject) => {
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if (xhr.readyState != 4) return;
if (xhr.readyState == 4 && xhr.status == 200) {
// 处理正常结果
resolve(xhr.responseText);
} else {
// 处理异常结果
reject('服务器错误');
}
};
xhr.open('get', url);
xhr.send(null);
});
} var promise1 = queryData('http://localhost:3000/a1');
var promise2 = queryData('http://localhost:3000/a2');
var promise3 = queryData('http://localhost:3000/a3'); Promise.race([promise1, promise2, promise3]).then(result => {
console.log(result);
});
</script>
</body>
</html>

11.async和await:

​ ①背景:上文说到如果不熟悉promise,那么它的链式调用无异于看天书,这时候async和await就应运而生,很好的解决了这个问题。

​ ②.什么是async和await:

​ async顾名思义是“异步”的意思,async用于声明一个函数是异步的。而await从字面意思上是“等待”的意思,就是用于等待异步完成。并且await只能在async函数中使用。

​ ③async和await的作用:

​ 比promise更直观,更具有可读性

12.async / await的基本用法:

​ 通常async、await都是跟随Promise一起使用的。为什么这么说呢?因为async返回的都是一个Promise对象同时async适用于任何类型的函数上。这样await得到的就是一个Promise对象(如果不是Promise对象的话那async返回的是什么 就是什么,await得到Promise对象之后就等待Promise接下来的resolve或者reject。

 async function testSync() {
2 const response = await new Promise(resolve => {
3 setTimeout(() => {
4 resolve("async await test...");
5 }, 1000);
6 });
7 console.log(response);
8 }
9 testSync();//async await test...

13.async / await的深入用法

1.async函数返回一个promise对象,如果在async函数中返回一个直接量,async会通过Promise.resolve封装成Promise对象。

我们可以通过调用promise对象的then方法,获取这个直接量。

async function test(){
return "Hello World";
} var result=test();
console.log(result);
//打印Promise { 'Hello World' }

2.如果async函数不返回值:

async function test(){

}
var result=test();
console.log(result);
//打印Promise { undefined }

3.await的用法:

①说明:await会暂停当前async的执行,await会阻塞代码的执行,直到await后的表达式处理完成,代码才能继续往下执行。

await后的表达式既可以是一个Promise对象,也可以是任何要等待的值。

如果await等到的是一个 Promise 对象,await 就忙起来了,它会阻塞后面的代码,等着 Promise 对象 resolve,然后得到 resolve 的值,作为 await 表达式的运算结果。

②注意事项:await堵塞非promise的异步函数是无效的

1.基本用法:

function A() {
return "Hello ";
} async function B(){
return "World";
} async function C(){
//等待一个字符串
var s1=await A();
//等待一个promise对象,await的返回值是promise对象resolve的值,也就是"World"
var s2=await B();
console.log(s1+s2);
} C();
//打印"Hello World"

2.进阶用法:

1.async实现链式回调且没有定义then/catch实现的函数,默认走resolve(),而调用resolve默认会打印传进去的参数的值

​ 结果: 输出11 一秒后再打印22

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
async function testSync() {
console.log(await getAsync("11"));
console.log(await getAsync("22"));
}
function getAsync(param){
return new Promise((resolve,reject)=>{
setTimeout(function(){
resolve(param)
},1000)
})
}
testSync();
</script> </body>
</html>

2.async实现链式回调但是定义了then/catch实现的函数,resolve默认输出的是undefined

结果: 输出 "11" undefined

一秒后输出: "22" undefined

<script>
//async的返回值是一个promise
async function testSync() {
console.log(await getAsync("11"));
console.log(await getAsync("22"));
}
function getAsync(param){
return new Promise((resolve,reject)=>{
setTimeout(function(){
resolve(param)
// reject(param)
},1000)
}).then(function(){
console.log(param);
}).catch(function(){
console.log("err");
})
} testSync()
</script>

​ 3.处理机制:

​ 区别:函数里面多了个await

​ ①串行处理

 1 async function asyncAwaitFn(str) {
2 return await new Promise((resolve, reject) => {
3 setTimeout(() => {
4 resolve(str)
5 }, 1000);
6 })
7 }
8
9 const serialFn = async () => { //串行执行
10
11 console.time('serialFn')
12 console.log(await asyncAwaitFn('string 1'));
13 console.log(await asyncAwaitFn('string 2'));
14 console.timeEnd('serialFn')
15 }
16
17 serialFn(); ###string 1
###string 2
###serialFn: 2007.7892ms

​ ②并行处理:

 1 async function asyncAwaitFn(str) {
2 return await new Promise((resolve, reject) => {
3 setTimeout(() => {
4 resolve(str)
5 }, 1000);
6 })
7 }
8 const parallel = async () => { //并行执行
9 console.time('parallel')
10 const parallelOne = asyncAwaitFn('string 1');
11 const parallelTwo = asyncAwaitFn('string 2')
12
13 //直接打印
14 console.log(await parallelOne)
15 console.log(await parallelTwo)
16
17 console.timeEnd('parallel')
18
19
20 }
21 parallel() ### string1
### string2
### parallel: 1009.3232
###比串行快了一倍

​ 4.错误处理:

​ JavaScript异步请求肯定会有请求失败的情况,上面也说到了async返回的是一个Promise对象。既然是返回一个Promise对象的话那处理当异步请求发生错误的时候我们就要处理reject的状态了。在Promise中当请求reject的时候我们可以使用catch。为了保持代码的健壮性使用async、await的时候我们使用try catch来处理错误。

<script>
async function catchErr() {
try {
const errRes = await new Promise((resolve, reject) => {
setTimeout(() => {
reject("http error...");
}, 1000)}
) }
catch(err) {
console.log(err);
}
} catchErr(); //http error... </script>

14.宏任务和微任务

​ 1.概念: 宏任务和微任务表示异步任务的两种分类。常见的宏任务: setTimeout、setInterval, 常见的微任务: Promise、then、catch、finally

​ 2.基本执行顺序 : 主线程(外层宏) --> 微 --> 宏

​ ①基本示例1:

//  1  1.1  -  2  -  3
setTimeout(() => {
console.log('3')
}, 0)
console.log('1'); new Promise((resolve) => {
console.log('1.1');
resolve()
}).then(() => {
console.log('2');
}).then(()=>{
console.log('2.1')
})

​ ②基本示例2:

 console.log('1');
setTimeout(function () {
console.log('3');
new Promise(function (resolve) {
console.log('3.1');
resolve();
new Promise(function (resolve) {
console.log('9.1');
resolve();
}).then(function () {
console.log('9.2')
})
}).then(function () {
console.log('4')
})
}) new Promise(function (resolve) {
console.log('1.1');
resolve();
}).then(function () {
console.log('2')
}) setTimeout(function () {
console.log('5');
new Promise(function (resolve) {
console.log('5.1');
resolve();
}).then(function () {
console.log('6')
})
})

​ ③基本示例3:

 console.log('1');
setTimeout(function () {
console.log('3');
new Promise(function (resolve) {
console.log('3.1');
resolve();
new Promise(function (resolve) {
console.log('9.1');
resolve();
}).then(function () {
console.log('9.2')
})
}).then(function () {
console.log('4')
})
}) new Promise(function (resolve) {
console.log('1.1');
setTimeout(function(){
console.log("8");
})
resolve();
}).then(function () {
console.log('2')
}) setTimeout(function () {
console.log('5');
new Promise(function (resolve) {
console.log('5.1');
resolve();
}).then(function () {
console.log('6')
})
})
输出结果是: 1、1.1、2、3、3.1、9.1、9.2、4、8、5、5.1

3.宏任务和微任务的总结:

​ 先执行主线程的东西,宏任务和微任务加入队列,主线程执行完之后,执行微任务队列(先进先出的原则),微任务如果包含宏任务,也先丢到宏任务后面,微任务执行完,最后执行宏任务

参考博客:

https://www.cnblogs.com/lemonib/p/10087356.html

Promise和await、同步和异步的更多相关文章

  1. 异步解决方案----Promise与Await

    前言 异步编程模式在前端开发过程中,显得越来越重要.从最开始的XHR到封装后的Ajax都在试图解决异步编程过程中的问题.随着ES6新标准的到来,处理异步数据流又有了新的方案.我们都知道,在传统的aja ...

  2. promise、async、await、settimeout异步原理与执行顺序

    一道经典的前端笔试题,你能一眼写出他们的执行结果吗? async function async1() { console.log("async1 start"); await as ...

  3. 【Mocha.js 101】同步、异步与 Promise

    前情提要 在上一篇文章<[Mocha.js 101]Mocha 入门指南>中,我们提到了如何用 Mocha.js 进行前端自动化测试,并做了几个简单的例子来体验 Mocha.js 给我们带 ...

  4. 前端综合学习笔记---异步、ES6/7、Module、Promise同步 vs 异步

    同步 vs 异步 先看下面的 demo,根据程序阅读起来表达的意思,应该是先打印100,1秒钟之后打印200,最后打印300.但是实际运行根本不是那么回事 console.log(100) setTi ...

  5. js的事件循环机制:同步与异步任务(setTimeout,setInterval)宏任务,微任务(Promise,process.nextTick)

    javascript是单线程,一切javascript版的"多线程"都是用单线程模拟出来的,通过事件循环(event loop)实现的异步. javascript事件循环 事件循环 ...

  6. promise async await使用

    1.Promise (名字含义:promise为承诺,表示其他手段无法改变) Promise 对象代表一个异步操作,其不受外界影响,有三种状态: Pending(进行中.未完成的) Resolved( ...

  7. 用 async/await 来处理异步

    昨天看了一篇vue的教程,作者用async/ await来发送异步请求,从服务端获取数据,代码很简洁,同时async/await 已经被标准化,是时候学习一下了. 先说一下async的用法,它作为一个 ...

  8. js同步、异步、回调的执行顺序以及闭包的理解

    首先,记住同步第一.异步第二.回调最末的口诀 公式表达:同步=>异步=>回调 看一道经典的面试题: for (var i = 0; i < 5; i++) { setTimeout( ...

  9. 用async/ await来发送异步

    昨天看了一篇vue的教程,作者用async/ await来发送异步请求,从服务端获取数据,代码很简洁,同时async/await 已经被标准化,是时候学习一下了. 先说一下async的用法,它作为一个 ...

  10. 【转】用 async/await 来处理异步

    原文地址:https://www.cnblogs.com/SamWeb/p/8417940.html 昨天看了一篇vue的教程,作者用async/ await来发送异步请求,从服务端获取数据,代码很简 ...

随机推荐

  1. URAL2127 Determinant of a Graph 题解

    这个题真的折磨了我超久的.全网几乎搜不到一个详细的题解,俺来写写吧. 题意:给你一个无自环无重边的连通无向图,求它邻接矩阵的行列式的值. \(n\le 2*10^5,n-1\le m \le n+50 ...

  2. MySQL 常用命令(3)------表基本操作

    五.表的基本操作 1.创建表 语法:create table <表名> ( <字段名1> <类型1> [,..<字段名n> <类型n>]); ...

  3. 实现MybatisPlus乐观锁

    1.实体类中添加version字段及相关注解 @Version@TableField(fill = FieldFill.INSERT)//第一次添加数据时使其有个默认值1private Integer ...

  4. MFC编辑框字符显示时无法换行的问题解决

    字符串结尾加上"\r\n": 编辑框属性设置:Auto HScroll为False,Multiline为True,Want Return为True.

  5. 实验 四 [bx]和loop的使用

    1. 综合使用 loop,[bx],编写完整汇编程序,实现向内存 b800:07b8 开始的连续 16 个 字单元重复填充字数据0403H. 代码  assume cs:code code segme ...

  6. python——NLP关键词提取

    关键词提取顾名思义就是将一个文档中的内容用几个关键词描述出来,这样这几个关键词就可以提供这个文档的大部分信息,从而提高信息获取效率. 关键词提取方法同样分为有监督和无监督两类,有监督的方法比如构造一个 ...

  7. docker-compose实践(携程apollo项目)

    docker-compose使用开源镜像启动容器 以携程apollo项目为例,使用docker-compose部署单节点模式 创建apollo文件夹,vim一个新的docker-compose.yam ...

  8. JavaScript 取消事件的默认动作

    preventDefault() 方法 Event 对象 定义和用法 取消事件的默认动作. 语法 event.preventDefault() 说明 该方法将通知 Web 浏览器不要执行与事件关联的默 ...

  9. python 浮点除法

    昨天晚上久违地去打了次div2 一年没打,挂得很惨 早上起来试着用python写一遍唯一写出来的a题 然后发现了一个奇怪的现象 代码如下(为了方便观察已经改过了,不是解题的代码) import sys ...

  10. 攻防(一)tomcat CVE-2020-1938 ftp 21端口

    TOMCAT kali自带POE msf6 > use auxiliary/admin/http/tomcat_ghostcat set RHOST 10.98.xx.xx msf6 auxil ...