一、promise
promise是ES6引入的异步编程的新解决方案。语法上promise是一个构造函数,用来封装异步操作并可以获取其成功或者失败的结果。
1.promise构造函数:Promise(excutor){}
2.Promise.prototype.then方法
3.Promise.prototype.catch方法
4.实例化一个Promise对象p
const p=new Promise(function(resolve,reject) {
//开始异步封装操作
//调用resolve时,p就是成功
});
5.在异步封装操作中调用resolve(data)或者reject(err)时,实例就可以调用promise对象的then方法
p.then(function(value){},function(reason){ })
then方法有两个函数参数,函数有形参,成功的形参一般叫value,失败的形参叫reason。
如果已经调用了成功的方法,失败的方法就不会执行。
<script>
//实例化promise对象
const p=new Promise(function(resolve,reject) {
//开始封装异步操作
setTimeout(function () {
//得到一些数据
let data='数据库中的用户数据';
let err='数据读取失败';
//可以调用resolve、reject来改变p的状态(初始化、成功、失败)
//调用resolve时,p就是成功
resolve(data);
//调用reject时,p是失败
reject(err);
},1000);
});
//当p的状态是成功时,调用promise对象的then方法
p.then(function(value){
//成功状态下
console.log(value);//数据库中的用户数据
},function(reason){
//失败状态下,
console.log(reason);
})
</script>
二、promise封装读取文件
//引入fs模块
const fs=require('fs');
//使用Promise封装异步操作读取文件
const p=new Promise(function(resolve,reject){
//异步操作readFile
fs.readFile("../resources/文件.md",(err,data)=>{
//如果失败
if(err){
reject(err);
}else{//成功
resolve(data);
}
})
});
p.then(function(value){
console.log(value);
},function(reason){
console.log("读取失败")
});
三、promise封装ajax
<script>
// 接口地址: https://api.apiopen.top/getJoke
const p = new Promise((resolve, reject) => {
//1. 创建对象
const xhr = new XMLHttpRequest();
//2. 初始化
xhr.open("GET", "https://api.apiopen.top/getJ");
//3. 发送
xhr.send();
//4. 绑定事件, 处理响应结果
xhr.onreadystatechange = function () {
//判断
if (xhr.readyState === 4) {
//判断响应状态码 200-299
if (xhr.status >= 200 && xhr.status < 300) {
//表示成功
resolve(xhr.response);
} else {
//如果失败
reject(xhr.status);
}
}
}
})
//指定回调
p.then(function(value){
console.log(value);
}, function(reason){
console.error(reason);
});
</script>
四、Promise.prototype.then方法
调用then方法,then方法的返回结果是promise对象,对象状态由回调函数的执行结果决定。
- 如果回调函数中的返回结果是非promise类型的数据,状态为成功,返回值为对象的成功的值。
const result= p.then(function(value){
console.log(value);
//1.非promise类型的数据
return 111;
})
},function(reason){
console.warn(reason);
})
console.log(result);
//当前result状态是成功,值就是111
- 返回结果是promise类型的数据,返回的是promise对象,如果是调用成功状态,那么then方法返回的也是成功,返回值就是调用成功或者失败状态的值。
const result= p.then(function(value){
console.log(value);
return new Promise((resolve,reject)=>{
//resolve('ok');
reject('error');//如果调用失败,那么then也是失败,返回值就是error
})
}
resolve('ok')时,当前调用then方法的返回值也就是result的状态也是resolve成功,值是ok。
reject('error')同理
- 抛出错误
throw new Error("出错了");
当前result的状态也是reject,值就是抛出的值:出错了
可以使用链式调用
p.then(value=>{
console.log(value);
return new Promise((resolve,reject)=>{
reject('ok')
})
},reason=>{
}).then(value=>{
console.log(value);
},reason=>{
console.log('111')//111
})
实例:读取多个文件:解决回调地狱
//引入fs模块
const fs=require('fs');
//使用promise实现
const p=new Promise((resolve,reject)=>{
fs.readFile("./ES/promise/resources/文件.md",(err,data)=>{
resolve(data);//当前p的状态是成功,data是文件.md
});
});
p.then(value=>{
//console.log(value.toString());
return new Promise((resolve,reject)=>{
fs.readFile("./ES/promise/resources/文件2.md",(err,data)=>{
resolve([value,data]);//放在一个数组中
});
})
}).then(value=>{
//console.log(value.toString());
return new Promise((resolve,reject)=>{
fs.readFile("./ES/promise/resources/文件3.md",(err,data)=>{
value.push(data);
resolve(value);
});
})
}).then(value=>{
console.log(value.join('\r\n'));//拼接
})
五、Promise.prototype.catch方法
catch指定promise失败的回调
<script>
//catch指定promise失败的回调
const p=new Promise((resolve,reject)=>{
setTimeout(()=>{
reject('出错');
},1000)
})
p.catch(function(reason){
console.warn(reason);
})
</script>