一、promise 的理解
promise
是什么,如下所示:
Promise
是一门新的技术(ES6
规范)Promise
是 JS
中进行异步编程的新解决方案- 从语法上来说:
Promise
是一个构造函数 - 从功能上来说:
promise
对象用来封装一个异步操作并可以获取其成功/
失败的结果值
promise
的状态改变,如下所示:
pending
变为 resolved
pending
变为 rejected
- 只有这
2
种, 且一个 promise
对象只能改变一次 - 无论变为成功还是失败, 都会有一个结果数据
- 成功的结果数据一般称为
value
, 失败的结果数据一般称为 reason
promise
指定回调函数的方式更加灵活,如下所示:
- 旧的: 必须在启动异步任务前指定
promise
: 启动异步任务 => 返回 promie
对象 => 给 promise
对象绑定回调函数(甚至可以在异步任务结束后指定/多个)
promise
支持链式调用, 可以解决回调地狱问题,如下所示:
- 回调地狱,回调函数嵌套调用, 外部回调函数异步执行的结果是嵌套的回调执行的条件
- 回调地狱的缺点,不便于阅读,不便于异常处理
- 解决方案,
promise
链式调用 - 终极解决方案,
async/await
二、promise 的使用
promise
的初体验,代码如下所示:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>promise 基本使用</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;
}
const btn = document.querySelector('#btn');
btn.addEventListener('click', function () {
const p = new Promise((resole, reject) => {
setTimeout(() => {
let n = rand(1, 100);
if (n <= 30) {
resole(n);
} else {
reject(n);
}
}, 1000);
});
console.log(p);
p.then((value) => {
alert('您的中奖数字为' + value);
}, (reason) => {
alert('您的号码为' + reason);
});
});
</script>
</body>
</html>
promise
的 fs
模块,代码如下所示:
const fs = require('fs');
let p = new Promise((resolve, reject) => {
fs.readFile('./resource/content.txt', (err, data) => {
if (err) reject(err);
resolve(data);
});
});
p.then(value => {
console.log(value.toString());
}, reason => {
console.log(reason);
});
promise
的 ajax
封装,代码如下所示:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<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>
<div class="container">
<h2 class="page-header">promise 封装 ajax</h2>
<button class="btn btn-primary" id="btn">点击发送 ajax 请求</button>
</div>
<script>
const btn = document.querySelector('#btn');
btn.addEventListener('click', function () {
const p = new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.open('GET', 'https://api.apiopen.top/getJoke');
xhr.send();
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
if (xhr.status >= 200 && xhr.status < 300) {
resolve(xhr.response);
} else {
reject(xhr.status);
}
}
}
});
p.then(value => {
console.log(value);
}, reason => {
console.warn(reason);
});
});
</script>
</body>
</html>
promise
的封装 fs
模块,代码如下所示:
function mineReadFile (path) {
return new Promise((resolve, reject) => {
require('fs').readFile(path, (err, data) => {
if (err) reject(err);
resolve(data);
});
});
}
mineReadFile('./resource/content.txt').then(value => {
console.log(value.toString());
}, reason => {
console.log(reason);
});
util.promisify
方法,代码如下所示:
const util = require('util');
const fs = require('fs');
let mineReadFile = util.promisify(fs.readFile);
mineReadFile('./resource/content.txt').then(value => {
console.log(value.toString());
});
promise
封装 ajax
,代码如下所示:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>promise 封装 ajax</title>
</head>
<body>
<script>
function sendAJAX () {
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.responseType = 'json';
xhr.open('GET', url);
xhr.send();
xhr.onreadystatechange = function () {
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>