阅读 142

promise的用法

promise的定义

它是一个ES6提出一个新语法,用来优化异步代码的写法

构造器

const p = new Promise(function(resolve,reject){
  
})复制代码
  • 构造器必须要给定一个参数,如果不给就是会报错。例如,new Promise() 报错的信息是: Promise resolver undefined is not a function

  • 构造器的实参是一个函数,这个函数的特殊之处在于它有两个形参(resolve,reject),这两个形参也是函数。在格式上,也可以采用箭头函数来改写。例如:var p1 = new Promise((resolve,reject)=>{})

  • 在函数体的内部, 一般会执行异步代码,然后根据情况来调用resolve()或者是reject() 。调用resolve或者是reject后会产生什么样的后果,在后面小节介绍。 当然了,再次强调一下resolve和reject只是形参名,可以改写成其它的。

三种状态和值

一个Promise对象的状态可能是如下三种之一:pending,resolved,rejected 。下面分别介绍。

初始态pending

pending。它的意思是 "待定的,将发生的",相当于是一个初始状态。 创建Promise对象时,且没有调用resolve或者是reject方法,相当于是初始状态。这个初始状态会随着你调用resolve,或者是reject函数而切换到另一种状态。 这个初始状态就是你对别人说出承诺的那个瞬间,此时,大家都不知道这个承诺是否能兑现。

成功态resolved

也有叫fulfilled的。

resolved。表示解决了,就是说这个承诺实现了。 要实现从pending到resolved的转变,需要在 创建Promise对象时,在函数体中调用了resolve方法(即第一个参数)。

失败态rejected

rejected。拒绝,失败。表示这个承诺没有做到,失败了。要实现从pending到rejected的转换,只需要在创建Promise对象时,调用reject函数。

注意:状态转换是不可逆的。
一旦从pending ---> resolved(或者是rejected),就不可能再回到pending,也不能由resolved变成rejected。复制代码

promise的值

一个promise对象除了状态之外,还有promiseValue。在构造器中,这个值在调用resolve和reject方法时传入

promise的兑现

在构造器的函数体中,一旦状态发生了变化,就会进行then,或者是catch中去,同时把promiseValue传入对应的函数。

具体来说:

  • 状态从pending变成resolved,进入then中,调用函数,并传入此时的promiseValue(就是调用resolve时传入的实参)

  • 状态从pending变成rejected,进入catch中,调用函数,并传入此时的promiseValue(就是调用reject时传入的实参)

使用promise改造回调函数

第一步:建立模板。这里的模板是指固定的套路:写一个空函数,在函数体中的创建一个promise对象,并返回。

function getPromise(){
  const p =new Promise((resolve,reject)=>{

  })
  return p 
}复制代码

当然, 如果使用箭头函数的话,还可以简化成这样:

const getPromise = ()=> new Promise((resolve,reject)=>{})复制代码

第二步:把异步功能写入构造器中,根据实际来决定是否调用resolve,reject。 第三步:调用函数。

通过`getPromise().then().catch()` 结构来调用这个函数。复制代码
getPromise().then((res)=>{
  console.log(res)
}).catch((err)=>{
  console.log(err)
})复制代码

then的格式及执行逻辑

then的格式

它有两个参数,每个参数都是函数。 第二个参数是可选的。 它的两个参数都是函数。

  • 第一个参数是resolved状态的回调函数。当p的状态从pending变成了resolved,函数1会执行。

  • 第二个参数是rejected状态的回调函数。 当p的状态从pending变成了rejected,函数2会执行。

执行逻辑

var p = new Promise((resolved,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方法的并不是同一个对象。 看下如下代码:

const p1 = new Promise(()=>{})
const p2 = p1.then((res)=>{},(err)=>{})

console.log(p1 === p2) // false复制代码

如上代码可以说明p1.then()的结果是一个与p1不同的promise对象。换句话说,then()会封装一个全新的promise对象p2。那既然 p2也是一个promise对象,那么,p2的状态(promiseStatus)和值(promiseValue)分别是什么?

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的格式及用法

Promise.prototype.catch 是 Promise.prototype.then(null, reject)的别名,用于指定当promise对象的状态从pending变成rejected的回调函数 。 catch的返回值仍是一个promise对象,确定它的值的方式与then(null,(errVal)=>{ })的方式一致。

async-await语法

async,await 是es7中新增的语法,用来进一步改进异步代码的写法,是promise升级版!async函数返回一个 Promise 对象。

async函数内部return语句返回的值是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) })复制代码

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>


作者:没事多来康康我
链接:https://juejin.cn/post/7015101935921397796


文章分类
后端
文章标签
版权声明:本站是系统测试站点,无实际运营。本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 XXXXXXo@163.com 举报,一经查实,本站将立刻删除。
相关推荐