Promise介绍
ES6教程传送门:es6.ruanyifeng.com/#docs/promi…
Promise 是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更合理和更强大。它由社区最早提出和实现,ES6 将其写进了语言标准,统一了用法,原生提供了Promise
对象。
所谓Promise
,简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。从语法上说,Promise 是一个对象,从它可以获取异步操作的消息。Promise 提供统一的 API,各种异步操作都可以用同样的方法进行处理。
Promise
对象有以下两个特点。
(1)对象的状态不受外界影响。Promise
对象代表一个异步操作,有三种状态:pending
(进行中)、fulfilled
(已成功)和rejected
(已失败)。只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。这也是Promise
这个名字的由来,它的英语意思就是“承诺”,表示其他手段无法改变。
(2)一旦状态改变,就不会再变,任何时候都可以得到这个结果。Promise
对象的状态改变,只有两种可能:从pending
变为fulfilled
和从pending
变为rejected
。只要这两种情况发生,状态就凝固了,不会再变了,会一直保持这个结果,这时就称为 resolved(已定型)。如果改变已经发生了,你再对Promise
对象添加回调函数,也会立即得到这个结果。这与事件(Event)完全不同,事件的特点是,如果你错过了它,再去监听,是得不到结果的。
注意,为了行文方便,本章后面的resolved
统一只指fulfilled
状态,不包含rejected
状态。
有了Promise
对象,就可以将异步操作以同步操作的流程表达出来,避免了层层嵌套的回调函数。此外,Promise`对象提供统一的接口,使得控制异步操作更加容易。
Promise
也有一些缺点。首先,无法取消Promise
,一旦新建它就会立即执行,无法中途取消。其次,如果不设置回调函数,Promise
内部抛出的错误,不会反应到外部。第三,当处于pending
状态时,无法得知目前进展到哪一个阶段(刚刚开始还是即将完成)。
如果某些事件不断地反复发生,一般来说,使用 Stream 模式是比部署Promise
更好的选择。
1.什么是Promise
Promise是构造函数, 用于创建promise实例对象
作用 : 解决回调地狱
回调地狱 : 异步回调,层层嵌套
promise场景: 让异步代码按照同步的顺序执行,并且避免回调嵌套
代码演示地狱回调
//需求: 依次读取文件a , b , c
const fs = require('fs')
/* 如何让异步代码按照顺序执行 : 异步嵌套 */
//读取文件a
fs.readFile(`${__dirname}/data/a.txt`, 'utf-8', (err, data) => {
if (err) {
throw err
} else {
console.log(data)
//读取文件b
fs.readFile(`${__dirname}/data/b.txt`, 'utf-8', (err, data) => {
if (err) {
throw err
} else {
console.log(data)
//读取文件c
fs.readFile(`${__dirname}/data/c.txt`, 'utf-8', (err, data) => {
if (err) {
throw err
} else {
console.log(data)
//读取文件d
fs.readFile(`${__dirname}/data/d.txt`, 'utf-8', (err, data) => {
if (err) {
throw err
} else {
console.log(data)
}
})
}
})
}
})
}
})
2. Promise使用流程: 两个步骤
2.1 创建Promise实例对象 :
let p = new Promise((resolve,reject)=>{
//异步代码
if( 成功 ){
//调用resolve() 就会执行then第一个回调
resolve(数据)
}else{
//reject() 就会执行then第二个回调
reject(错误信息)
}
})
2.2 调用promise实例的then方法 :
p.then( res=>{
//成功
} , err=>{
//失败
})
3. Promise原理 : Promise本质是一个容器
3.1 Promise有三种工作状态
进行中 pending
已成功 fulfilled
已失败 rejected
3.2 Promise状态切换只有两种情况
从pending(进行中)变成fulfilled(已成功)
从pending(进行中)变成rejected(已失败)
3.3 promise创建的时候里面的代码会立即执行
(1)不要在promise里面去处理异步结果
(2)而是执行promise的resolve与reject方法
3.4 promise解决回调地狱:
在上一个promise对象的then方法中返回 下一个promise对象
p1.then(res=>{ return p2 })
.then( res=>{ } )
总结 : promise本身无法控制异步顺序(异步无序的),只是控制 异步结果的 顺序
4.promise其他用法(了解)
catch : 捕捉promise对象的异常错误信息
all : 将多个promise放入数组中合并成一个promise, 只有数组中所有的promise执行完毕才会执行then
代码介绍
let p1 = createPromise('a')
let p2 = createPromise('b')
let p3 = createPromise('c')
// Promise.all( [p1,p2,p3] ) : 多个promise对象合并成一个
let pAll = Promise.all( [p1,p2,p3] )
//(2)调用then方法
pAll.then(res=>{
//上面所有的promise全部都执行完毕,才会执行then
console.log(res)
}).catch(err=>{
console.log(err)
})
race :将多个promise放入数组中合并成一个promise, 只要数组中任意promise执行完毕就会执行then
async异步函数
1. async异步函数 : 相当于 promise 的更高级写法
async关键字: 修饰 异步函数,让函数支持await
await关键字: 阻塞当前函数执行,等待promise的resolve()结果
2. async使用两个流程
2.1 使用async关键字修饰函数: async function 函数名(){}
2.2 在async函数中用await来执行promise : let res = await promise实例对象
异步函数使用流程
(1)使用async关键字修饰函数 : 让这个函数内部可以识别await关键字
(2)使用await关键字调用 promise异步 , await的结果就是 promise内部的resolve()结果
代码演示
async function fn() {
//res1就是await后面那个promise的then里面的res
let res1 = await readPromise('a')
console.log(res1)
let res2 = await readPromise('b')
console.log(res2)
let res3 = await readPromise('c')
console.log(res3)
}
fn()