一、什么是Promise
1、Promise是ES6引入的异步编程的新解决方案。语法上Promise是一个构造函数,用来封装异步操作并可以获取其成功或失败的结果。
二、Promise基本语法
1、Promise接收一个函数类型的参数。这个函数有两个入参。入参名字可以叫resolve和reject。
2、把异步函数封装在Promise对象中,成功调用resolve(),失败调用reject()。
//实例化 Promise 对象
const p = new Promise(function(resolve, reject){
setTimeout(function(){
//模拟获取数据
let data = '数据库中的用户数据';
//调用resolve
resolve(data);
//调用后p的状态会变成成功
}, 1000);
});
//调用 Promise 对象的 then 方法
p.then(function(value){ //它有两个形参,成功的形参叫value
//当你调用resolve(),Promise对象状态为成功时,调用第一个函数
console.log(value);
}, function(reason){ //失败的形参叫reason
//如果调用reject(),Promise对象状态为失败,调用第二个函数
console.error(reason);
});
一秒钟后,控制台打印:数据库中的用户数据
3、Promise构造函数:Promise(excutor){}
4、Promise.prototype.then方法
5、Promise.prototype.catch方法
三、Promise读取文件
1、例子使用了nodejs的fs库
Promise读取文件.js
//1. 引入 fs 模块
const fs = require('fs');
//2. 调用方法读取文件
// fs.readFile('./let关键字.html', (err, data) => {
// //如果失败,则抛出错误
// if(err) throw err;
// //如果没有出错,则输出内容
// console.log(data.toString());
// });
//3. 使用Promise封装
const p = new Promise(function(resolve, reject){
fs.readFile('./let关键字.html', (err, data) => {
//判断如果失败
if (err) reject(err);
//如果成功
resolve(data);
});
})
p.then(function(value){
console.log(value.toString());
}, function(reason){
console.log("读取失败!");
});
执行:
D:\workspace-vscode\ECMAScript6> node .\Promise读取文件.js
2、要是有多个异步任务,代码要不断的往里面缩进,但是使用Promise就不会。
四、Promise封装ajax请求
1、接口地址:https://api.apiopen.top/api/sentences
const p = new Promise((resolve, reject)=>{
//1. 创建对象
const xhr = new XMLHttpRequest();
//2. 初始化
xhr.open("GET", "https://api.apiopen.top/api/sentences");
//3. 发送
xhr.send();
//4. 绑定事件,处理响应结果
xhr.onreadystatechange = function(){
//判断
if(xhr.readyState === 4){
//判断响应状态码
if(xhr.status >= 200 && xhr.status <300){
//表示成功
//console.log(xhr.response);
resolve(xhr.response);
}else{
//如果失败
//console.error(xhr.status);
reject(xhr.status);
}
}
}
});
//指定回调
p.then(function(value){
console.log(value);
}, function(reason){
console.error(reason);
});
Promise把调用和数据处理分开来了,代码更简洁。
五、Promise.prototype.then方法
1、如果回调函数中返回的结果是非 Promise 类型的属性,则返回对象状态为成功,对象的值为返回值。
//创建 Promise 对象
const p = new Promise((resolve, reject)=>{
setTimeout(()=>{
resolve('用户数据');
}, 1000);
});
//调用 then 方法,两个回调函数
const result = p.then(value=>{
console.log(value);
return 123;
}, reason=>{
console.warn(reason);
});
//then 方法的返回结果是 Promise 对象,对象状态是由回调函数的执行结果决定的
console.log(result);
2、状态
pending:初始状态,不是成功或失败状态。
fulfilled:意味着操作成功完成。
rejected:意味着操作失败。
3、如果回调函数返回的是 Promise 对象,则 then 方法返回的就是这个对象。
4、then链式调用
p.then(value=>{}, reason=>{}).then(value=>{}, reason=>{});
链式调用,可以避免回调地狱的现象。
六、Promise读取多个文件,解决回调地狱现象
1、挨个读取三个文件内容,将读的内容合在一起输出
//1. 引入 fs 模块
const fs = require("fs");
//回调地狱方式实现
// fs.readFile('./let关键字.html', (err1, data1)=>{
// fs.readFile('./const关键字.html', (err2, data2)=>{
// fs.readFile('./let关键字实例.html', (err3, data3)=>{
// let result = data1 + + '\r\n' + data2 + '\r\n' + data3;
// console.log(result);
// });
// });
// });
//使用 Promise 实现
//读取第一个文件
const p = new Promise((resolve, reason)=>{
fs.readFile('./let关键字.html', (err1, data1)=>{
//成功
resolve(data1);
});
});
//第一个Promise的回调
p.then(value=>{
//返回一个新的Promise读取第二个文件
return new Promise((resolve, reject)=>{
fs.readFile("./const关键字.html", (err, data2)=>{
//成功
resolve([value, data2]); //value是读第一个文件的返回,data2是读第二个文件的返回
});
});
}).then(value=>{
return new Promise((resolve, reject)=>{
fs.readFile("./let关键字实例.html", (err, data3)=>{
//成功
value.push(data3); //压入
resolve(value); //value是三个文件的返回结果的数组
});
});
}).then(value=>{
console.log(value.join('\r\n'));
});
七、Promise的catch方法
1、catch方法
用来指定Promise对象失败的一个回调。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Promise的catch方法</title>
<style>
</style>
</head>
<body>
<h1 id="hid" class="hcls"><span>test</span></h1>
</body>
<script>
const p = new Promise((resolve, reject)=>{
//模拟操作
setTimeout(()=>{
//设置p对象的状态为失败,并设置失败的值
reject("出错啦!");
}, 1000);
});
// p.then(value=>{}, reason=>{
// console.error(reason);
// });
//catch只回调状态失败时的回调方法
p.catch(reason=>{
console.warn(reason);
});
</script>
</html>