JavaScript异步编程 期约Promise

期约是为了简化异步编程而设计的语言特性。

使用new Promise()构造函数可以新建一个期约,该函数接收一个函数作为参数,我们先传入一个空函数:

const p=new Promise(()=>{})
console.log(p)
// 输出: Promise { <pending> }

上述输出表示期约的状态,目前为<pending>

上面的函数参数又可以接收如下两个函数参数:

  • resolve() : 可将期约的状态变为resolved
  • reject() : 可将期约的状态变为rejected

示例如下:

const p=new Promise((resolve,reject)=>resolve())
console.log(p)
// 输出:Promise { undefined }

这个表示期约的值是undefined,期越的状态是resolved(默认)。

现在,给定一个期约值:

const p=new Promise((resolve,reject)=>resolve(1))
console.log(p)
//输出: Promise { 1 }

如下代码将期约变为rejected状态:

const p=new Promise((resolve,reject)=>reject(1))
console.log(p)
// 输出: Promise { <rejected>  1 }

这个输出结果表示期约当前的状态是rejected,期约值是1。同时,此时控制台会输出一些错误信息,我们先不管它。

通过打印期约对象,我们可以发现,期约分为三种状态:

(1)pending
(2)resolved
(3)rejected

期约的状态决定了后续的操作是调用then()还是调用catch()。期约值是期约链式操作的数据流转的第一步。

除了构造函数以外,可以使用如下方式快速创建期约:

const  p1= Promise.resolve(1)
console.log(p1)
// 输出:Promise { 1 }

const  p2= Promise.reject(1)
console.log(p2)
//输出: Promise { <rejected> 1 }

期约的实例方法和期约链

多层串联的回调函数本质上是多个函数的链式操作,上一个函数的返回值作为参数传递给下一个函数,使用期约对象的then()方法,就能实现链式操作,例如:

const p = Promise.resolve(1)

p.then(x=>x+1)
.then(x=>x*2)
.then(x=>console.log(x))   //=>4

期约对象的链式操作有三个方法:then()、catch()、finally()。这三个方法都接收一个函数作为参数,表示下一步的操作。

当期约对象的状态变为resolved时,就可以调用then(),例如:

const p = Promise.resolve(1)
p.then(x=>x+1)
           .then(x=>x*2)
           .then(x=>console.log(x))   //=>4

当期约对象的状态变为rejected时,就可以调用catch(),不过,一次正常的catch()之后,状态就会变为resolved,例如:

const p= Promise.reject(1)
p.catch(x=>x+1)
             .then(x=>x*2)
             .then(x=>console.log(x))   //输出:4

期约对象无论是什么状态,都可以调用finally()。如下:

const p= Promise.reject(1)
p.finally(()=>console.log('期约链开始'))
         .catch(x=>x+1)             
         .then(x=>x*2)
         .then(x=>console.log(x))
         .finally(()=>console.log('期约链停止'))  

期约链是一个串行操作,像流水线一样,每道工序可能包含:自己的操作、流转的数据,如果不显式或隐式地使用return为下一个操作提供数据,那么该步操作会直接将上一步的数据流转到下一步。

也就是说,每一步肯定有一个流转数据,就看你用不用、处不处理,每一步也肯定会输出流转数据到下一步。流转的数据就是每一步都回调函数的第一个参数,如下示例:

const p= Promise.resolve(1)        
p.then((x)=>console.log('期约链开始'))
         .then(x=>{
               x=x+1                                
              return 3                    
          })
         .then(x=>x*2)                      
         .then((x)=>console.log(`现在流转的数          据是${x}`))

在上面这个例子中,由Promise.resolve()产生期约链条的流转数据1,每一步的操作其实就是一个箭头函数,箭头函数的第一个参数是流转的数据,函数体是对流转数据的处理或其它行为,第一个then()没有对流转数据进行处理,所以直接往下传递。第二个then()对流转数据进行处理,但是显式地return 3,此时流转数据就是3。第三个then()对流转数据乘以2,注意,根据箭头函数的规则,这一行其实隐式地return了6。最后一个then()是获取流转数据并输出。

由上面的几个例子还可以看出,期约的链式操作是打平的,解决了以往的回调函数层层嵌套的问题,写法上更直观,理解起来也更直接。不过,人们
对语法简洁性的追求是无限的,比起不断地使用then(),还有个更简洁的方式,那就是使用await。

  • 12
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值