434 ES6 的 Promise,async,await,all,race,三个状态
-
Promise 是 es6 提出来的一个非常重要的一个语法
-
Promise 是一种
处理异步
的解决方案
通过同步编写代码
的方式,处理异步
的一种解决方案
-
以前 : 处理异步 是怎么处理的 ? 回调
这种回调处理异步 可以的, 简单的情况下 使用 回调处理还凑活, 但是异步请求次数多, 复杂的话, 回调地狱
缺点 :
1. 代码不优雅
2. 结构不清晰
3. 处理起来不方便.....
setTimeout( ()=> {},1000)
$.ajax({
url : '..',
data : {},
success : res => {
}
})
// 顺序
// 第一次发送请求
$.ajax({
url : '..',
data : {},
success : res => {
// 第二次发送请求
$.ajax({
url : '..',
data : {},
success : res => {
// 第三次发送请求
$.ajax({
url : '..',
data : {},
success : res => {
}
})
}
})
}
})
- 解决方式 : Promise
Promise.then( res => {
//第一次发送请求
})
.then(res => {
//第二次发送请求
})
.then(res => {
// 第三次发送请求
})
02-Promise的基本使用.js
/**
* 1. Promise是一个构造函数
* 2. () 参数里是一个回调函数
* resolve : fn => 异步操作成功, 调用resolve
* reject : fn => 异步操作失败, 调用 reject
* 3. Promise里面放一个异步操作
*/
/**
* 1. p 是 Promise 类型
* 2. axios.get() 都是promise类型
* 3. promise的类型的实例,都可以点then
* axios.get().then()
* axios.post().then()
* p.then()
* XXX.then()
*/
// 自己封装的 promise
const p = new Promise((resolve, reject) => {
setTimeout(() => {
// console.log('异步操作开始了');
// 如果异步操作成功 => 调用 resolve => 走 实例对象的then => 传参数
// resolve('成功的信息')
// 如果异步操作失败 => 调用 reject => 走 实例对象的catch => 传参数
reject('这是一条错误信息')
}, 0);
})
// 供别人调用的
p.then(res => {
console.log('then被调用了: ', res);
})
.catch(err => {
console.log('catch 被调用了: ', err);
})
03-Promise的注意点.js
/**
* 自定义封装Promise
* 1. Promise 构造函数
* 2. () 回调函数
* resolve
* reject
* 3. Promise里面放一个异步操作
*/
const p = new Promise((resolve, reject) => {
setTimeout(() => {
// 成功
resolve('这是成功消息')
// 失败
// reject()
}, 0)
})
const p = new Promise((resolve, reject) => {
setTimeout(() => {
// 成功
resolve('这是成功消息')
// 失败
// reject()
}, 0)
})
p.then(res1 => {
console.log('then 被调用了1:', res1) // 这是成功消息
}).then(res2 => {
console.log('then 被调用了2: ', res2); // undefined 【因为上一个then没有指定return返回值,默认返回就是undefined。】
}).then(res3 => {
console.log('then 被调用了3', res3); // undefined
return 1111
}).then(res4 => {
console.log('then 被调用了4', res4); // then 被调用了4 1111
})
// 注意点1 : p .then().then().then().then() .catch()...是链式编程 每次调用返回的都是 promise类型
// 注意点2 :
// 第一个then, 拿到的是promise类型的p中resolve返回给我们的值,
// 第二个then, 拿到的确实undefined, 因为 p.then() => 新的promise类型实例,resolve()是空的
// 后面的.then() 出来的都是新的promise实例
// .catch(err => {
// console.log('catch 被调用了')
// })
// 链式编程
// p.then().catch()
04-使用Promise封装一个异步读取 文件.js
//1. 引入 模块
const fs = require('fs')
//3. 使用 Promise 封装起来
const p = new Promise((resolve,reject) => {
fs.readFile('./a1.txt', 'utf-8', (err, data) => {
if (err) {
// 执行reject,并且用return 退出函数执行
return reject('读取失败');
}
// console.log(data)
resolve(data)
})
})
p.then(res => {
console.log('then : ',res);
})
.catch(err => {
console.log('catch:',err);
})
//2 异步读取 文件
// fs.readFile('./a.txt', 'utf-8', (err, data) => {
// if (err) {
// return console.log('读取失败')
// }
// console.log(data)
// })
05-使用Promise封装一个异步读取多个文件.js
// 1. 引入 模块
const fs = require('fs')
// 2. 封装promise
function ml_readF(filepath) {
const p = new Promise((resolve, reject) => {
fs.readFile(filepath, 'utf-8', (err, data) => {
if (err) {
return reject('读取失败')
}
resolve(data)
})
})
return p
}
// 3. 使用
// ml_readF('./a.txt') 读取 a.txt 的 promise
ml_readF('./a.txt')
.then(res1 => {
console.log('then :', res1)
return ml_readF('./b.txt')
})
.then(res2 => {
console.log('then : ', res2)
return ml_readF('./c.txt')
})
.then(res3 => {
console.log('then :', res3)
})
// p.then(res1 => {
// console.log('then :',res1);
// })
06-async和await.js
套路:
使用 promise 封装异步操作函数fn,返回promise 实例,
使用async、await 封装操作 fn的函数。
/**
* async 和 await 是 es8 提出来的一个语法
* 想`同步编写代码`的方式`处理异步`, 处理的更加彻底
* async: 修饰一个内部有异步操作的函数, 格式: async + 函数
* await: 等待一个异步操作的结果, 格式: await 异步操作(promise类型)
*/
// 1. 引入 模块
const fs = require('fs')
// 2. 封装promise
function ml_readF(filepath) {
const p = new Promise((resolve, reject) => {
fs.readFile(filepath, 'utf-8', (err, data) => {
if (err) {
return reject('读取失败')
}
resolve(data)
})
})
return p
}
//3. 需求: 先后读取 a.b.c (都是异步的)
// ml_readF('./a.txt').then(res => {
// console.log(res);
// })
// async: 修饰一个内部有(await)异步操作的函数 【不能用箭头函数。】
async function fn() {
// 格式 : await + promise类型
// 结果 : let a = ? a 就是以前 then(res => res的结果 )
let a = await ml_readF('./a.txt')
console.log(a) // aaaa
let b = await ml_readF('./b.txt')
console.log(b) // 大傻春
let c = await ml_readF('./c.txt')
console.log(c) // 小马哥
}
fn()
07-async和await的注意点.js
/**
* async 修饰一个内部有异步操作的函数 async + 函数
* await 等待一个异步操作的结果 let res = await 异步操作(promise类型)
*/
// 1. 引入 模块
const fs = require('fs')
// 2. 封装promise
function ml_readF(filepath) {
const p = new Promise((resolve, reject) => {
fs.readFile(filepath, 'utf-8', (err, data) => {
if (err) {
return reject('读取失败')
}
resolve(data)
})
})
return p
}
/**
* 注意点1 : async 和 await 成对出现
* 注意点2 : async 添加的函数,一定是await `最近`的函数
* 注意点3 : async 和 await 如果要处理异常,配合使用 try...catch
*/
async function fn1() {
// 【读取 b、c的代码放在 try中,读取 a,就报错,终端执行,不会往下读b、c,说明 await 是同步/阻塞的。】
try {
// 读取 a
let a = await ml_readF('./a1.txt')
console.log(a)
} catch (error) { // 捕获 异常
console.log('读取a失败了'); // 读取a失败了
}
// 读取 b
let b = await ml_readF('./b.txt')
console.log(b); // 大傻
// 读取 c
let c = await ml_readF('./c.txt')
console.log(c); // 小马哥
}
fn1()
08-尝试改造axios.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Document</title>
</head>
<body>
<script src="./node_modules/axios/dist/axios.js"></script>
<script>
/* */
/* axios
.get(
'http://localhost:8888/api/private/v1/login?username=admin&password=123456'
)
.then(res => {
console.log(res)
})
let p = axios
.get(
'http://localhost:8888/api/private/v1/login?username=admin&password=123456'
)
console.log(p); // Promise对象 */
// 既然 axios.get() 就是一个promise类型 就可以使用 async 和 await 改造
// async 修饰一个函数
// await 等待一个结果
async function fn() {
let res = await axios.get('http://localhost:8888/api/private/v1/login?username=admin&password=123456')
console.log(res)
}
fn()
</script>
</body>
</html>
09-Promise的其他两个方法的使用.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Document</title>
</head>
<body>
<!--
需求1 : 想让三个异步请求都完成了, 再执行我们的操作
Promise.all([n个异步请求])
需求2 : 只要其中的一个完成了,就可以执行我的操作 (竞赛)
Promise.race()
-->
<!--
json-server的url规则:http://localhost:3000/ + key
data.json的数据:
{
"one": [11, 12, 13, 14],
"two": [21, 22, 23, 24],
"three": [31, 32, 33, 34]
}
-->
<script src="./node_modules/axios/dist/axios.js"></script>
<script>
// Promise.race([
// axios.get('http://localhost:3000/one'),
// axios.get('http://localhost:3000/two'),
// axios.get('http://localhost:3000/three')
// ]).then(res => {
// console.log('res : ', res)
// console.log('开始我们的操作了')
// })
Promise.all([
axios.get('http://localhost:3000/one'),
axios.get('http://localhost:3000/two'),
axios.get('http://localhost:3000/three')
]).then(res => {
console.log('res : ', res)
console.log('开始我们的操作了')
})
</script>
</body>
</html>
10-Promise的三个状态.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Document</title>
</head>
<body>
<script>
/**
* 三个状态 :
* pending 等待/进行中
* resolved 操作成功
* rejected 操作失败
*/
const p = new Promise((resolve, reject) => {
setTimeout(() => {
reject()
}, 0)
})
console.log(p)
</script>
</body>
</html>
async, await
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>async函数</title>
</head>
<body>
<!--
async函数(源自ES2017)
概念: 真正意义上去解决异步回调的问题,同步流程表达异步操作
本质: Generator的语法糖
语法:
async function foo(){
await 异步操作;
await 异步操作;
}
特点:
1、不需要像Generator去调用next方法,遇到await等待,当前的异步操作完成就往下执行
2、返回的总是Promise对象,可以用then方法进行下一步操作
3、async取代Generator函数的星号*,await取代Generator的yield
4、语意上更为明确,使用简单,经验证,暂时没有副作用
-->
<script type="text/javascript" src="./js/jquery-1.10.1.min.js"></script>
<script type="text/javascript">
async function timeout(ms) {
return new Promise(resolve => {
setTimeout(resolve, ms);
})
}
async function asyncPrint(value, ms) {
console.log('函数执行', new Date().toTimeString()); // 函数执行 17:42:33
await timeout(ms);
console.log('延时时间', new Date().toTimeString()); // 延时时间 17:42:35
console.log(value); // hello async
}
console.log(asyncPrint('hello async', 2000)); // Promise
// await
async function awaitTest() {
let result = await Promise.resolve('执行成功');
console.log(result); // 执行成功
let result2 = await Promise.reject('执行失败');
console.log(result2); // Promise {<rejected>: "执行失败"}
// 执行不了 【上一步报错了】
let result3 = await Promise.resolve('还想执行一次');
console.log(result3); //
}
awaitTest();
/*
// 案例演示
async function sendXml(url) {
return new Promise((resolve, reject) => {
$.ajax({
url,
type: 'GET',
success: data => resolve(data),
error: error => reject(error)
})
})
}
async function getNews(url) {
let result = await sendXml(url);
let result2 = await sendXml(url);
console.log(result, result2);
}
getNews('http://localhost:3000/news?id=2')
*/
</script>
</body>
</html>