文章目录
Promise简介
Promise是ES6引入的异步编程的新解决方案,语法上Promise是一个构造函数,用来封装异步操作并可以获取其成功或失败的结果。
promise的方法
- Promise构造函数:
Promise (excutor){}
Promise.prototype.then
方法
3)Promise.prototype.catch
方法
eg:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
</head>
<body>
<script>
// 实例化Promise对象
const p = new Promise(function (resolve,reject){
setTimeout(function (){
let data = '数据库中的数据'
resolve(data)//对象状态变成成功
/* let err = '数据读取失败'
reject(err)//对象状态变成失败*/
},1000)
});
// 调用promise对象的then方法,对应上面的resolve和reject
p.then(function (value){
// 状态是成功的时候调用该函数,即如果调用resolve就调用该函数
console.log(value)
},function (reason){
// 状态失败调用该函数,即如果调用reject就调用该函数
console.error(reason)
})
</script>
</body>
</html>
Promise有3种状态:初始化完成、成功、失败
Promise封装读取文件
不使用Promise读取文件
// 1.引入fs模块
const fs = require('fs');
// 2.调用方法读取文件
fs.readFile('./resources/为学.md', (err, data) => {
// 如果失败则抛出错误
if (err) throw err;
// 如果没出错则输出内容
console.log(data.toString());
})
Promise封装读取文件
// 1.引入fs模块
const fs = require('fs');
// 2.调用方法读取文件
// fs.readFile('./resources/为学.md', (err, data) => {
// // 如果失败则抛出错误
// if (err) throw err;
// // 如果没出错则输出内容
// console.log(data.toString());
// })
// 3. 使用Promise封装
const p = new Promise(function (resolve, reject) {
//读取文件是异步的
fs.readFile('./resources/为学.md', (err, data) => {
// 如果失败则抛出错误
if (err) reject(err);
// 如果成功
resolve(data);
})
})
p.then(function (value){
// 如果没出错则输出内容
console.log(value.toString());
},function (reason){
console.log('读取失败')
})
使用promise封装AJAX请求
<script>
const p = new Promise((resolve,reject)=>{
// Promise把AJAX请求包起来,看什么时候返回成功,什么时候返回失败
// 1创建对象
const xhr = new XMLHttpRequest()
// 2初始化
xhr.open('GET','https://api.apiopen.top/getJoke')
// 3发送
xhr.send()
// 4绑定事件按,处理响应结果
xhr.onreadystatechange = function (){
// 判断
if(xhr.readyState === 4){
if(xhr.status>=200&&xhr.status<300){
// 表示成功
resolve(xhr.response)
}else{
reject(xhr.status)
}
}
}
})
// 指定Promise的回调
p.then(function (value){
console.log(value)
},function (reason){
console.log(reason)
})
</script>
小结:Promise的优点
通过上述练习我们可以看出Promise的大致思路是,在Promise的构造函数中用resolve、reject
指出成功和失败的地方,然后再Promise.prototype.then
中指出成功和失败的回调函数。
所以使用Promise封装读取文件可以是代码结构更加清晰,减少代码缩进避免回调地狱,使代码更加精炼。
Promise.prototype.then方法
Promise.prototype.then方法的返回值
Promise.prototype.then方法的返回值也是一个Promise对象,它的状态由回调函数的执行结果决定:
- 如果回调函数中返回的结果是非promise 类型的属性,它的状态为成功,并且它的值为该回调函数中返回的结果。
eg:
<script>
// 实例化Promise对象
const p = new Promise((resolve,reject)=>{
setTimeout(()=>{
// resolve('用户数据')
reject('失败')
},1000)
});
const result = p.then(value=>{
console.log(value)
return 123
},reason=>{
console.error(reason)
return 456
})
console.log(result)
</script>
如果回调函数没有指定返回结果,那么默认值是返回undefine,不是Promise类型的,所以它的状态是成功
- 如果回调函数中返回的结果是promise 类型的属性,它的状态为该返回Promise的状态,并且它的值为返回Promise的值(参数)。
eg:
<script>
// 实例化Promise对象
const p = new Promise((resolve,reject)=>{
setTimeout(()=>{
resolve('用户数据')
// reject('失败')
},1000)
});
const result = p.then(value=>{
console.log(value)
return new Promise((resolve,reject)=>{
resolve('OK')
})
},reason=>{
console.error(reason)
return 456
})
console.log(result)
</script>
eg:
- 如果抛出错误,它的状态为失败,并且它的值为抛出来的值。
<script>
// 实例化Promise对象
const p = new Promise((resolve,reject)=>{
setTimeout(()=>{
resolve('用户数据')
// reject('失败')
},1000)
});
const result = p.then(value=>{
console.log(value)
throw new Error('出错啦')
},reason=>{
console.error(reason)
return 456
})
console.log(result)
</script>
then的链式调用
- 因为then的返回值有可能是Promise所以可以继续调用then,即链式调用。
eg:
p.then(
value=>{
},
reason=>{
}
).then(
value=>{
},
reason=>{
}
)
- then方法的回调函数中可以继续嵌套异步任务。
Promise解决回调地狱实例
实现多个文件读取:
- 普通写法(出现回调地狱)
// 引入fs模块
const fs = require('fs')
fs.readFile('./resources/为学.md', (err, data1) => {
fs.readFile('./resources/插秧诗.md', (err, data2) => {
fs.readFile('./resources/观书有感.md', (err, data3) => {
let result = data1 +'\n'+ data2 +'\n'+ data3
console.log(result)
})
})
})
输出:
- Promise实现
// 引入fs模块
const fs = require('fs')
const p = new Promise((resolve, reject) => {
fs.readFile('./resources/为学.md', (err, data) => {
resolve(data)
})
})
p.then(value => {
// value的值就是resolve或reject传过来的值
return new Promise((resolve, reject) => {
fs.readFile('./resources/插秧诗.md', (err, data) => {
resolve([value,data])//返回的是 为学的data和插秧诗的data
})
})
}).then(value => {
// 根据Promise的特性,此时.then,就是读取完插秧诗.then
return new Promise((resolve, reject) => {
fs.readFile('./resources/观书有感.md', (err, data) => {
value.push(data)
resolve(value)
})
})
}).then(value => {
console.log(value.join('\n'))
})
输出:
优点:不会出现回调地狱
Promise的catch参数
用来指定promise的失败回调
eg:
const p =new Promise((reslove,reject)=>{
setTimeout(()=>{
// 设置p对象
reject('失败了')
},1000)
})
p.catch(function (reason){
console.log(reason)
})
/*等价于
p.then(function (value){
},function (reason){
console.log(reason)
})*/