目录
1.7 util.promisify 方法进行Promise风格转化
1.Promise 的理解和使用
1.1. Promise 是什么?
1.1.1. 理解
构造函数进行对象的实例化
1.2. 为什么要用 Promise?
1.2.1. 指定回调函数的方式更加灵活
之前在进行异步任务之前必须把回调函数准备好
1.2.2. 支持链式调用, 可以解决回调地狱问题
回调地狱示例:
1.3 promise初体验
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>基本使用</title>
<link crossorigin='anonymous' href="https://cdn.bootcss.com/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div class="container">
<h2 class="page-header">Promise 初体验</h2>
<button class="btn btn-primary" id="btn">点击抽奖</button>
</div>
<script>
//生成随机数
function rand(m,n){
return Math.ceil(Math.random() * (n-m+1)) + m-1;
}
/**
点击按钮, 1s 后显示是否中奖(30%概率中奖)
若中奖弹出 恭喜恭喜, 奖品为 10万 RMB 劳斯莱斯优惠券
若未中奖弹出 再接再厉
*/
//获取元素对象
const btn = document.querySelector('#btn');
//绑定单击事件
btn.addEventListener('click', function(){
//定时器
// setTimeout(() => {
// //30% 1-100 1 2 30
// //获取从1 - 100的一个随机数
// let n = rand(1, 100);
// //判断
// if(n <= 30){
// alert('恭喜恭喜, 奖品为 10万 RMB 劳斯莱斯优惠券');
// }else{
// alert('再接再厉');
// }
// }, 1000);1s钟
//Promise 形式实现
//Promise在实例化时需要接受一个参数,这个参数是函数类型的值,resolve, reject是两个形参
// resolve 解决 函数类型的数据
// reject 拒绝 函数类型的数据
// 异步任务成功的时候调resolve,失败的时候调reject
//promise可以包裹异步操作,然后把异步操作代码setTimeout放进来
const p = new Promise((resolve, reject) => {
setTimeout(() => {
//30% 1-100 1 2 30
//获取从1 - 100的一个随机数
let n = rand(1, 100);
//判断
if(n <= 30){
resolve(n); // 将 promise 对象的状态设置为 『成功』
}else{
reject(n); // 将 promise 对象的状态设置为 『失败』
}
//把n当作结果值传递给resolve,reject的函数传给下面的value和reason
}, 1000);
});
console.log(p);
//调用 then 方法,指定成功或者失败时的回调,处理成功和失败的结果
// value 值 第一个参数是对象成功后的回调
// reason 理由 第二个参数是对象失败后的回调
p.then((value) => {
alert('恭喜恭喜, 奖品为 10万 RMB 劳斯莱斯优惠券, 您的中奖数字为 ' + value);
}, (reason) => {
alert('再接再厉, 您的号码为 ' + reason);
});
});
</script>
</body>
</html>
1.4 Promise实践练习——fs读取文件
//fs可以对计算机硬盘进行读写操作,
//本次读取resource底下content.txt
//首先引进fs模块
const fs = require('fs');
//回调函数(无promise的形式) 形式 err为出现错误时,data是我们要的参数,(err, data) => {是回调函数
// fs.readFile('./resource/content.txt', (err, data) => {
// // 如果出错 则抛出错误
// if(err) throw err;
// //输出文件内容
// console.log(data.toString());
//.toString()转成字符串
// });
//Promise 1.形式封装,首先创建promise对象,里面放一个异步任务
let p = new Promise((resolve , reject) => {
fs.readFile('./resource/content.txt', (err, data) => {
//如果出错
if(err) reject(err);
//如果成功
resolve(data);
});
});
//2.调用 then ,对结果进行处理
p.then(value=>{
console.log(value.toString());
}, reason=>{
console.log(reason);
});
1.5 Promise实践练习——Ajax请求
Promise步骤: 都一个路数,创建promise对象,把异步任务代码(就相当于原来的回调函数)放进去,成功时调resolve,失败调reject,顺便把成功和失败结果传进去,然后在then方法中指定成功和失败的回调,对结果进行处理
注意:实现异步编程:回调函数和Promise都行
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Promise 封装 AJAX</title>
<link crossorigin='anonymous' href="https://cdn.bootcss.com/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<!-- 案例点击按钮发送Ajax请求,给下面的接口地址发 -->
<div class="container">
<h2 class="page-header">Promise 封装 AJAX 操作</h2>
<button class="btn btn-primary" id="btn">点击发送 AJAX请求</button>
</div>
<script>
//接口地址 https://api.apiopen.top/getJoke
//获取元素对象,把按钮放进来
const btn = document.querySelector('#btn');
btn.addEventListener('click', function(){
//(2)创建 Promise实现异步
const p = new Promise((resolve, reject) => {
//(1)回调函数实现异步:Ajax四部操作 //1.创建对象
const xhr = new XMLHttpRequest();
//2. 初始化,给接口发get请求
xhr.open('GET', 'https://api.apiopen.top/getJoke');
//3. 发送
xhr.send();
//4. 绑定事件处理响应结果
xhr.onreadystatechange = function(){
if(xhr.readyState === 4){
//判断响应状态码 2xx开头是成功
if(xhr.status >= 200 && xhr.status < 300){
//控制台输出响应体(xhr.response)
// 使用回调函数就都用console.log打印
resolve(xhr.response);
}else{
//控制台输出响应状态码
reject(xhr.status);
}
}
}
});
//调用then方法
p.then(value=>{
console.log(value);
}, reason=>{
console.warn(reason);
});
});
</script>
</body>
</html>
1.6 Promise实践——封装fs读取文件操作
/**使用Promise的方式对读取文件进行了一个函数封装
* 封装一个函数 mineReadFile 作用是读取文件内容
// * 必须要在Node.js环境下运行,不能在浏览器中引入该文件
* 函数接受参数: path 文件路径,想读取的文件把路径传递给mineReadFile
* 返回: promise 对象,,成功结果为文件内容,失败结果为错误对象
*/
function mineReadFile(path){
//返回: promise 对象
return new Promise((resolve, reject) => {
//读取文件第一个参数为路径,第二个参数是回调
require('fs').readFile(path, (err, data) =>{
//判断
if(err) reject(err);
//成功
resolve(data);
});
});
}
// 调用函数读取,因为mineReadFile函数返回结果是一个Promise对象,所以可以直接调then
mineReadFile('./resource/content.txt')
.then(value=>{
//输出文件内容
console.log(value.toString());
}, reason=>{
console.log(reason);
});
1.7 util.promisify 方法进行Promise风格转化
/**promisify 方法属于util模块,错误优先回调,把这个方法给他,返回一个Promise版本
* util.promisify 方法
*/
// 以读取文件为例演示
//引入 util 模块
const util = require('util');
//引入 fs 模块
const fs = require('fs');
//返回一个新的函数,返回新函数的结果mineReadFile是一个promise对象
//util.promisify接受一个错误优先的方法
let mineReadFile = util.promisify(fs.readFile);
mineReadFile('./resource/content.txt').then(value=>{
console.log(value.toString());
});
//运行的时候在vscode里面不进浏览器,在底下的控制台输入Node 5-util.promisify 方法.js显示结果
//以后使用Promise,不需要每个方法都进行手动封装,而是借助util.promisify方法将原来回调函数的风格的方法转成mineReadFile-promise风格的函数
1.8 Promise封装AJAX操作
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Promise封装AJAX操作</title>
</head>
<body>
<script>
/**
* 封装一个函数 sendAJAX 发送 GET AJAX 请求
* 参数 URL
* 返回结果 Promise 对象
*/
function sendAJAX(url){
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.responseType = 'json';
//给url发
xhr.open("GET", url);
xhr.send();
//处理结果
xhr.onreadystatechange = function(){
//为4是所有结果都返回的状态
if(xhr.readyState === 4){
//判断成功
if(xhr.status >= 200 && xhr.status < 300){
//成功的结果
resolve(xhr.response);
}else{
reject(xhr.status);
}
}
}
});
}
sendAJAX('https://api.apiopen.top/getJok')
.then(value => {
console.log(value);
}, reason => {
console.warn(reason);
});
</script>
</body>
</html>
1.9 Promise对象属性状态介绍
Promise实例对象当中的一个属性叫promiseState
1.10 promise对象结果值属性介绍
resolve/reject可以修改这个值,then方法回调中才能把这个值取出来进行相关操作,不管成功失败,最终结果resolve/reject都保存在PromiseResult中
1.11 promise 的基本流程:
2. Promise相关的API
2.1这三个方法都属于实例化对象,剩下的方法都是属于Promise函数对象的
2.1 构造函数-then-catch
new promise来实例化对象,new的时候实例化要接收一个参数excutor
catch只能指定失败的回调,不能指定成功的回调
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Promise API</title>
</head>
<body>
<script>
//
let p = new Promise((resolve, reject) => {
// ** 同步调用
// console.log(111);
//修改 promise 对象的状态
reject('error');
});
//111和222是同步调用的
// console.log(222);
//执行 catch 方法指定失败的回调
p.catch(reason => {
console.log(reason);
});
</script>
</body>
</html>
2.2 Promise.resolve方法
Promise.resolve方法属于Promise这个函数对象的,不属于实例对象
作用:快速得到promise对象,而且还能封装一个值,将这个值转化为promise对象
<script>
let p1 = Promise.resolve(521);
//p1如果传入的参数为 非Promise类型的对象, 则返回的结果为成功promise对象
//p2如果传入的参数为 Promise 对象, 则参数的结果决定了 resolve 的结果,成功或失败
let p2 = Promise.resolve(new Promise((resolve, reject) => {
// resolve('OK');
reject('Error');
}));
// console.log(p2);上面如果是resolve('OK');打印出来的结果也是成功的promise,
//上面传进来成功的结果为ok,外层p2这和结果也是ok
//如果上面是失败的promise,下面就要有对应的回调来对失败结果进行处理,不能console.log
p2.catch(reason => {
console.log(reason);
})
</script>
2.3 Promise.reject方法
和resolve一样,这个方法属于Promise这个函数对象的,不属于实例对象
作用:快速返回一个失败的promise对象,可以将一个值快速转换成promise对象,只不过这个值是失败的,它接收一个参数,返回的结果一直是失败的promise对象
<script>
//返回的结果永远都是失败的,传入什么,失败的结果是什么
// let p = Promise.reject(521);
//无论你传入什么样的数值,返回结果都是失败的
// let p2 = Promise.reject('iloveyou');
let p3 = Promise.reject(new Promise((resolve, reject) => {
resolve('OK');
}));
//即便传入的是一个成功的promise对象,他的结果也是失败
//(状态是失败,而失败的结果是你传进来的这个成功的promise对象)
console.log(p3);
</script>
2.4 Promise.all方法
它接受的参数一般为 promise 组成的数组,这个参数结构里面每一个都是一个promise对象
返回结果也是一个promise对象
他的状态由数组中所有promise对象决定:数组中的promise对象都成功,则返回的这个promise对象才成功,有一个失败,返回结果就是失败的promise对象。
且成功的结果是数组中所有promise对象成功结果组成的一个数组;失败的结果是在这个数组中失败的那个promise对象的结果
<script>
let p1 = new Promise((resolve, reject) => {
resolve('OK');
})
// let p2 = Promise.resolve('Success');
let p2 = Promise.reject('Error');
let p3 = Promise.resolve('Oh Yeah');
//原来的//p2,三个都成功,all方法的返回结果是成功的promise,
//成功的结果是p1,p2,p3三个promise对象的成功结果组成的一个数组
//改完p2Promise.reject('Error');这样了就不成功了,返回失败结果Error
const result = Promise.all([p1, p2, p3]);
console.log(result);
</script>
2.5 Promise.race方法
它接受的参数一般为 promise 组成的数组,返回结果也是一个promise对象,与all有点像
它的结果状态:由第一个改变状态的promise对象决定,它成功race就成功,它失败race就失败,像Promise中在赛跑,谁先该改变状态,谁就决定race方法的返回结果
<script>
let p1 = new Promise((resolve, reject) => {
//设个异步任务
setTimeout(() => {
resolve('OK');
}, 1000);//1s钟以后才改变状态
})
let p2 = Promise.resolve('Success');
let p3 = Promise.resolve('Oh Yeah');
//没有异步任务的时候p1先改变,设了按照顺序就是p2
//调用
const result = Promise.race([p1, p2, p3]);
console.log(result);
</script>