Promise对象
特性
Promise为es6标准语法,主要用于解决异步回调问题,Promise 对象可分为三种状态。pending(进行中)、fulfilled(已成功)和rejected(已失败),Promise 状态为不可逆的,也就是说promise只能从pending->fulfilled,或从 pending -> rejected 由于异步操作的结果决定状态。一旦状态改变此对象将不能在复用。
示例
Promist 的基本用法本文章就不多做解释,总结其中特性。
let waitServerResponse = function(waitTime){
return new Promise((resolve, reject)=>{
if(waitTime>0){
setTimeout(()=>{
resolve(`服务器响应耗时:${waitTime}`)
},waitTime)
}else {
reject('系统故障')
}
})
}
waitServerResponse(3000).then((result)=>{
console.log(result) // 服务器响应耗时:3000
})
waitServerResponse(-1).then((success)=>{
console.log('进入success',success)
}).catch((err)=>{
console.log('捕获到失败状态:',err) // 捕获到失败状态: 系统故障
})
console.log('程序结束!')
/**
* 控制台输出:
* 捕获到失败状态: 系统故障
* console.log('程序结束!')
* 服务器响应耗时:3000
*/
由以上例子可以得出结论当我们发起一个Promise操作时 .then() 会在本轮 Javascript event loop(事件循环)运行完成才会执行,promise并不会阻塞后面代码执行,因此在我们想要执行类似请求执行完成得到某某结果后,在执行其他逻辑,就必须写在then函数里。
// 强烈不推荐使用此种嵌套写法用于工作中
waitServerResponse(3000).then((result)=>{
console.log(result)
waitServerResponse(-1).then((success)=>{
console.log('进入success',success)
}).catch((err)=>{
console.log('捕获到失败状态:',err) // 捕获到失败状态: 系统故障
console.log('程序结束!')
})
})
/**
* 控制台输出:
* 服务器响应耗时:3000
* 捕获到失败状态: 系统故障
* 程序结束!
*/
如果你一直都只是在这样使用promise那你并不能称得上会使用Promise这种用法同Ajax中请求中的回调函数如出一辙。根本就没有解决回调地狱的问题。(笔者在很长一段时间也用这种方式,并自以为乐😂😂😂)
链式调用
promise设计的目的就是想通过链式调用来解决回调问题。我们可以在then函数返回一个全新的promise来创造一个Promise chain。
waitServerResponse(3000).then((result)=>{
console.log(result)
return waitServerResponse(-1) // 使用return 创造 promise chain
}).then((success)=>{
console.log('进入success',success)
}).catch((err)=>{
console.log('捕获到失败状态:',err) // 捕获到失败状态: 系统故障
console.log('程序结束!')
})
// 还可以使用 => 语法 更加简化
waitServerResponse(3000)
.then(result => waitServerResponse(-1))
.then(success => console.log('进入success',success))
.catch(err => console.log('程序结束!'))
通过Promise chain 可以解决两个异步操作之前串行的问题,下面是Promise并行的场景。
组合
我当我门同时向服务器发送三次请求 请求分别要等待 3s、2s、1s,获取到全部数据后再执行相应操作。此时使用Promise chain理论耗时6s显然是不可取的,Promise提供了all()方法解决并行问题。
let request1 = waitServerResponse(3000)
let request2 = waitServerResponse(2000)
let request3 = waitServerResponse(1000)
Promise.all([request1,request2,request3,]).then((values) => {
console.log(values) // ["服务器响应耗时:3000", "服务器响应耗时:2000", "服务器响应耗时:1000"]
}
)
// 其中有任何promise状态为失败 都会被catch捕获
let request1 = waitServerResponse(3000)
let request2 = waitServerResponse(2000)
let request3 = waitServerResponse(-1)
Promise.all([request1,request2,request3,])
.then(values =>console.log(values))
.catch(errs=>{
console.log('catch======>',errs) // catch======> 系统故障
})
Promise 的理解到此为止,但promise还不是'回调问题'的最终解决方案,在es2017(es8)中提出 async/await方案下篇文章我们继续探讨。
参考文档:
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Guide/Using_promises
http://es6.ruanyifeng.com/#docs/promise