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. 用python3操作mysql数据库实现企业级产品参数查询

    Python3 MySQL 数据库连接 - PyMySQL 驱动 一.什么是 PyMySQL? PyMySQL 是在 Python3.x 版本中用于连接 MySQL 服务器的一个库,Python2中则 ...

  2. Javascript 基础知识,ajax,面向对象

    Javascript 数据类型 数据类型 基本数据类型 数字,字符串,布尔值 undefine null undefined的常见情形:ES6新语法提供的对象解构赋值应用讲解 1.1 对象属性不存在 ...

  3. 全新BPMN常用图形标识一览表

    BPMN符号与BPMN的关系 BPMN,即业务流程建模与标记(手法),表达此类手法的即是业务流程模型示意图.业务流程示意图是由一系列的元素符号构成.作为BPMN的基础,这些符号将业务流程建模简单化.图 ...

  4. C++ 手动实现双向链表(作业版)

    双向链表,并实现增删查改等功能 首先定义节点类,类成员包含当前节点的值, 指向下一个节点的指针和指向上一个节点的指针 //节点定义 template <typename T> class ...

  5. 策略模式demo

    /** StrategyContext. */ public class StrategyContext { private Strategy strategy; // 传入的是Strategy的实现 ...

  6. 波利亚(George Pólya)的一些链接

    忽然决定还是要写个博客. 第一篇献给波利亚. 他最有名的应该是<怎样解题>(How to solve it)这本书了.我认为只要读了前面几页就能提高普通人解决问题的能力,真的应该列为中学必 ...

  7. app自动化前置准备&环境搭建

    编写脚本之前的一些前置准备工作. 1,安装appium server:官网地址:http://appium.io/ 安装教程:https://www.cnblogs.com/gancuimian/p/ ...

  8. webpack1.x 之配置的坑

    一.静态资源目录改变(默认在dist下面) 默认: webpack配置 output: { path: path.join(__dirname, './dist'), filename: 'build ...

  9. xShell执行js脚本

    var CMD = 'ls'; var INTERVAL = 1; var MAX = 5; var CR = String.fromCharCode(13); var LF = String.fro ...

  10. Python 错误:TypeError: range() takes no keyword arguments

    问题描述: for循环时使用range()出错: for page in range(start=1, stop=8 + 1,step=1): print(page) 结果报错TypeError: r ...