promise作用
- promise是承诺的意思 它是一个ES6提出一个新语法,用来优化异步代码的写法
promise基本使用
构造器
// const obj = new Object()
// const arr = new Array()
const p1 = new Promise(function(resolve,reject){
// 执行异步代码
// 调用resolve,或者reject
});
console.dir(p1)
要点:
- 构造器必须要给定一个参数,如果不给就是会报错。例如,
new Promise()报错的信息是:Promise resolver undefined is not a function - 构造器的实参是一个函数,这个函数的特殊之处在于它有两个形参(resolve,reject),这两个形参也是函数。在格式上,也可以采用箭头函数来改写。例如:
var p1 = new Promise((resolve,reject)=>{})。 - 在函数体的内部, 一般会执行异步代码,然后根据情况来调用resolve()或者是reject() 。调用resolve或者是reject后会产生什么样的后果,在后面小节介绍。 当然了,再次强调一下resolve和reject只是形参名,可以改写成其它的。
三种状态和值
初始状态pending
- pending。它的意思是 "待定的,将发生的",相当于是一个初始状态。 创建Promise对象时,且没有调用resolve或者是reject方法,相当于是初始状态。这个初始状态会随着你调用resolve,或者是reject函数而切换到另一种状态
var p = new Promise((resolve,rejectok,err)=>{ console.info('发呆.....' )})
console.dir(p)
成功态resolved 也叫fulfilled😁😁
- resolved。表示解决了,就是说这个承诺实现了。 要实现从pending到resolved的转变,需要在 创建Promise对象时,在函数体中调用了resolve方法(即第一个参数)
var p = new Promise((resolve,reject)=>{ resolved();})
console.dir(p)
最后一个失败态rejected🤦♂️🤦♂️
rejected。拒绝,失败。表示这个承诺没有做到,失败了。要实现从pending到rejected的转换,只需要在创建Promise对象时,调用reject函数
var p = new Promise((resolve,reject)=>{ reject()} )
console.dir(p)
三种状态小结
- 状态是可转化。
- 最初创建promise对象时,默认状态是pending,如果在函数体内部调用了第一个参数对应的函数,则状态变成了resolved;如果调用了第二个参数对应的函数,则状态变成了rejected
pending ----- resolve() --> resolved;
pending ----- reject() --> rejected;
- 状态转换是不可逆的。
- 一旦从pending ---> resolved(或者是rejected),就不可能再回到pending,也不能由resolved变成rejected
promise的兑现
在构造器的函数体中,一旦状态发生了变化,就会进行then,或者是catch中去,同时把promiseValue传入对应的函数。
具体来说:
- 状态从pending变成resolved,进入then中,调用函数,并传入此时的promiseValue(就是调用resolve时传入的实参)
- 状态从pending变成rejected,进入catch中,调用函数,并传入此时的promiseValue(就是调用reject时传入的实参)
then的格式及执行逻辑
作用
- then方法的作用是为Promise对象添加状态改变时的回调函数。
- 下面从其调用格式,执行逻辑及返回值三个方面来介绍
then的格式😶🌫️😶🌫️
它有两个参数,每个参数都是函数。 第二个参数是可选的。
// p 是一个promise对象
p.then(函数1[,函数2])
它的两个参数都是函数。
- 第一个参数是resolved状态的回调函数。当p的状态从pending变成了resolved,函数1会执行。
- 第二个参数是rejected状态的回调函数。 当p的状态从pending变成了rejected,函数2会执行。
其中第二个参数是可选的,如果只写一个参数的话就是如下:
promise对象.then(函数1)
看一个执行逻辑
var p = new Promise((resolve,reject)=>{
// resolve(val1);
reject(val2)
})
p.then(
okVal=>{
console.info("成功");
console.log(okValue);
},
errVal=>{
console.info("失败");
console.log(errValue);
}
)
它的两个参数都是函数,其执行逻辑是:
- 如果promise对象的状态是resolved,则then()会执行第一个函数,并传入当前的PromiseValue(即上面的val1);
- 如果promise对象的状态是rejected,则then()会执行第二个函数,并传入当前的PromiseValue(即上面的val2);
- 特别地,如果promise对象的状态是rejected,且此时then方法并没有设置第二个参数,就会向外抛出一个错误,错误的提示大约是
Uncaught (in promise)。
then的返回值(难点)
- then()方法的返回值也是一个promise对象,所以它支持链式写法。但是要注意的是它的返回值是一个新的promise对象,与调用then方法的并不是同一个对象
var p1 = new Promise(()=>{});
var p2 = p1.then(function f_ok(){}, function f_err(){});
// p2也是一个promise对象。
console.log(p1 === p2); // false
p2的状态及promiseValue如何确定?
p2的状态及promiseValue按如下规则来确定
- 如果p1的状态是pending,则p2的状态也是pending。
- 如果p1的状态是resolved,then()会去执行f_ok,则p2的状态由f_ok的返回值决定。
- 如果f_ok返回值不是promise对象,则p2的状态是resolved,且p2的promiseValue就是f_ok函数的return值。
- 如果f_ok返回值是一个promise对象,则p2的状态及promiseValue以这个promise对象为准。
- 如果f_ok这个函数内部发生了错误(或者是用户主动抛出错误),则p2的状态是rejected,且p2的promiseValue就是这个错误对象。
- 如果p1的状态是rejected,then()会去执行f_err,则p2的状态由f_err的返回值决定。
- 如果f_err返回值不是promise对象,则p2的状态是resolved,且p2的promiseValue就是f_err函数的return值。
- 如果f_err返回值是一个promise对象,则p2的状态及promiseValue以这个promise对象为准。
- 如果f_err这个函数内部发生了错误(或者是用户主动抛出错误),则p2的状态是rejected,且p2的promiseValue就是这个错误对象
catch的格式及用法
catch 是 then(null, reject)的别名
catch()的格式及用法
Promise.prototype.catch 是 Promise.prototype.then(null, reject)的别名,用于指定当promise对象的状态从pending变成rejected的回调函数 。
catch的返回值
catch的返回值仍是一个promise对象,确定它的值的方式与then(null,(errVal)=>{ })的方式一
如果您看到这里了 请坚持看下去 你会发现上面的所有都不懂都没有关系 只需要记住下面我写的代码就行
async-await语法(重点)
async,await 是es7中新增的语法,用来进一步改进异步代码的写法,是promise升级版
async
async函数返回一个 Promise 对象。
function f1 () {
return 1
}
async function f2 () {
return 1
}
async function f3 () {}
const r1 = f1()
const r2 = f2()
const r3 = f3()
console.log(r1) // 1
console.log(r2) // Promise, resolved(1)
console.log(r3) // Promise, resolved(undefined)
r2.then(res => { console.log(res) })
r3.then(res => { console.log(res) })
async函数内部return语句返回的值是Promise 对象的值
await 命令
-
await的外层函数必须有一个async
-
正常情况下,await命令后面是一个 Promise 对象,返回该promise的值。如果不是 Promise 对象,就直接返回对应的值。
<script>
async function f() {
const p = new Promise((resolve,reject)=>{
resolve(100)
})
const a = 1
// await 等待promise的状态变化完成(pending->resolved, pending->rejected)
// 取出promise的值
const b = await p
console.log(a,b)
}
f()
</script>
async函数内部的执行流程
在执行async函数(设名为asyncF)时,进入函数内部
- 按序执行同步代码
- 遇到await,跳出asyncF函数,