目录
1.3.1 Promise 构造函数:Promise(excutor) { }
1.3.2 Promise.prototype.then 方法: then((value) => {}, (reason) => {})
1.3.3 Promise.prototype.catch 方法:catch((reason) => {})
1.3.4 Promise.resolve 方法: Promise.resolve(value)
1.3.5 Promise.reject 方法: Promise.reject(reason)
1.3.6 Promise.all 方法: Promise.all(promise)
1.3.7 Promise.race 方法: Promise.race(promise)
1.4.2 一个 promise 指定多个 成功 / 失败 回调函数,都会调用吗?
1.4.3 改变 promise 状态和指定回调函数谁先谁后?
1.4.4 promise.then() 返回的新的 promise 的结果状态由什么决定?
2.2 执行器函数的 两个参数 resolve 和 reject 改变状态的函数结构搭建
3.5.3 可以和axios结合使用,axios返回的是一个promise
练习代码地址:GitHub - climber-lx/x-Promise
一、Promise 的理解和使用
1.1 Promise 是什么?
1.1.1 理解
1.抽象表达
1.Promise 是一门新的技术(ES6规范)。
2.Promise 是 JS 中进行异步编程的新解决方案
备注:旧方案是单纯使用回调函数
2.集体表达
1.从语法上来说: Promise 是一个构造函数
2.从功能是哪个来说:promise 对象用来封装一个异步操作并可以获取其成功/失败的结果值。
异步编程
node 中的 fs 文件操作:
require('fs').readFile('./index.html',(err, data) => {});
数据库操作
AJAX
$.get('/server', (data)=>{})
定时器
setTimeout(()=>{},2000)
1.1.2 promise 的改变状态
promise的状态
实例中的一个属性 【PromiseStatus】
pedding 未决定的
resolved / fullfilled 成功
rejected 失败
Promise 对象的值
实例中的一个属性 【PromiseResult】 then 方法return的值
保存着异步任务 【成功/失败】的结果
1. pending变为 resolved
2. pending变为 rejected
说明:只有这2种,且一个 promise 对象只能改变一次
无论变成成功还是失败,都会有一个结果数据
成功的结果数据一般称为value,失败的结果一般称为reason
1.1.3 promise 的基本流程
1.2 为什么要用 Promise ?
1.2.1 指定回调函数的方式更加灵活
1.旧的:必须在启动异步任务前指定
2.promise:启动异步任务 => 返回 promise 对象 => 给 promise 对象绑定回调函数(甚至可以异步任务技术后指定/多个)
1.2.2 支持链式调用,可以解决回调地狱问题
1.什么是回调地狱?
回调函数嵌套调用,外部回调函数异步执行的结果是嵌套的回调执行的条件。
2.回调地狱的缺点?
不便于阅读、不便于异常处理
3.解决方案?
promise 链式调用
4.终极解决方案?
promise 和 async结合使用。
1.2.3 案例理解
1.中奖概率
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>基本使用</title>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css" integrity="sha384-HSMxcRTRxnN+Bdg0JdbxYKrThecOKuH5zCYotlSAcp1+c8xmyTe9GYg1l9a69psu"
crossorigin="anonymous">
</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);
}
/**
点击按钮,2s后显示是否中奖(30%概率中奖)
若中奖弹出 恭喜恭喜,奖品为10万RMB 劳斯莱斯优惠券
若未中奖弹出 再接再厉
*/
// 获取元素对象
const btn = document.querySelector('#btn');
btn.addEventListener('click', function () {
// 定时器
// setTimeout(() => {
// let n = rand(1, 100);
// if (n <= 30) {
// alert('恭喜恭喜,奖品为10万RMB 劳斯莱斯优惠券');
// } else {
// alert('再接再厉');
// }
// }, 1000);
// promise 形式实现
// resolve 解决 函数类型的数据
// reject 拒绝 函数类型的数据
const p = new Promise((resolve, reject) => {
setTimeout(() => {
let n = rand(1, 100);
if (n <= 30) {
resolve(n); // 将 promise 对象的状态设置为 【成功】
} else {
reject(n); // 将 promise 对象的状态设置为 【失败】
}
}, 1000);
})
p.then((value) => {
alert('恭喜恭喜,奖品为10万RMB 劳斯莱斯优惠券,您的中奖号码为' + value);
}, (reason) => {
alert('再接再厉,您的号码为' + reason);
})
})
</script>
</body>
</html>
2.获取文件内容
const fs = require('fs');
// 回调函数 形式
// fs.readFile('./resource/content.txt', (err, data) => {
// // 如果出错
// if (err) throw err;
// // 输出文件内容
// console.log(data.toString());
// })
// promise 形式
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);
})
3.发送ajax请求
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>promise时间练习</title>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css" integrity="sha384-HSMxcRTRxnN+Bdg0JdbxYKrThecOKuH5zCYotlSAcp1+c8xmyTe9GYg1l9a69psu"
crossorigin="anonymous">
</head>
<body>
<div class="container">
<h2 class="page-header">Promise 初体验</h2>
<button class="btn btn-primary" id="btn">点击抽奖</button>
</div>
<script>
// 接口地址:https://api.apiopen.top/getJoke
const btn = document.querySelector('#btn');
let url = "https://api.apiopen.top/getJoke";
btn.addEventListener('click', function () {
const p = new Promise((resolve, reject) => {
// 1.创建对象
const xhr = new XMLHttpRequest();
// 2.初始化
xhr.open('GET', url);
// 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);
}
}
}
})
p.then((value) => {
console.log(value);
}, (reason) => {
console.log(reason);
})
})
</script>
</body>
</html>
4.封装- fs模块练习
/**
* 封装一个函数 minReadFile 读取文件内容
* 参数:path 文件路径
* 返回:promise对象
*
*/
function minReadFile(path) {
return new Promise((resolve, reject) => {
require('fs').readFile(path, (err, data) => {
// 判断
if (err) reject(err);
resolve(data);
})
})
}
minReadFile('./resource/content.txt').then((value) => {
console.log(value.toString());
}, (reason) => {
console.log(reason);
})
5.使用node util
/**
* util.promisify 方法
*/
// 引入 util 模块
const util = require('util');
// 引入fs模块
const fs = require('path');
// 返回一个新的函数
let mineReadFile = util.promisify(fs.readFile);
mineReadFile('./resource/content.txt').then((value) => {
console.log(value.toString());
}, (reason) => {
console.log(reason);
})
6.封装-发送ajax
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>promise封装AJAX练习</title>
</head>
<body>
<script>
/*
封装一个函数 sendAJAX 发送 GET AJAX 请求
参数 URL
返回结果 promise 对象
*/
function sendAJAX(url) {
return new Promise((resolve, reject) => {
// 1.创建对象
const xhr = new XMLHttpRequest();
// 指定返回的数据格式
xhr.responseType = 'json';
// 2.初始化
xhr.open('GET', url);
// 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);
}
}
}
})
}
let url = "https://api.apiopen.top/getJoke";
sendAJAX(url).then((value) => {
console.log(value);
}, (reason) => {
console.log(reason);
})
</script>
</body>
</html>
1.3 Promise API
1.3.1 Promise 构造函数:Promise(excutor) { }
(1) excutor 函数:执行器 (resolve, reject) => { }
(2) resolve 函数:内部定义成功时调用的函数;resolve(result)。 回调函数:value => { }
(3) reject 函数:内部定义失败时调用的函数;reject(error)。回调函数:reason => { }
说明:excutor 会在 Promise 内部立即同步调用,异步操作在执行器中执行。
// excutor 函数: 执行器 ((resolve, reject) => {})
let p = new Promise((resolve, reject) => {
})
1.3.2 Promise.prototype.then 方法: then((value) => {}, (reason) => {})
(1) resolve() 函数:成功的回调函数。value => { }
(2) reject() 函数:失败的回调函数。reason => { }
说明:指定用于得到成功 value 的成功回调和用于得到失败 reason 的失败回调返回一个新的 promise 对象。
// excutor 函数 ((resolve, reject) => {})
let p = new Promise((resolve, reject) => {
// 同步调用的
console.log(111);
// resolve('success');
reject('faild');
})
// then(参数1,参数2)
// 参数1 和 参数2 都是函数类型
// 参数1: resolve():成功的回调函数
// 参数2: reject():失败的回调函数
// 参数2可以不写,只写一个参数时为成功的回调函数。
p.then((value) => {
console.log(value); // success
}, (reason) => {
console.log(reason); //faild
})
console.log(p);
// 如果then 方法中不设置返回值,then方法返回结果为一个成功的promise,返回值为 undefined
// 如果有返回值,类型为 非promise 时,then方法返回一个成功的promise,返回值为 输出的返回值。
// 如果有返回值且为promise类型,则根据返回的promise来决定返回的promise的状态和结果。
// 如果then中抛出异常,则根据当前的状态返回一个promise对象,返回值为抛出的值
1.3.3 Promise.prototype.catch 方法:catch((reason) => {})
(1) reject() 函数:失败的回调函数。reason => { }
let p = new Promise((resolve, reject) => {
// 同步调用的
console.log(111);
// resolve('success');
reject('faild');
})
// reject() 错误的回调函数
p.catch((reason) => {
console.log(reason); //faild
})
1.3.4 Promise.resolve 方法: Promise.resolve(value)
(1) value: 成功的数据或promise对象
说明:返回一个 成功/失败 的 promise 对象
如果传入的参数为 非Promise 类型的对象,则返回的结果为成功 promise,结果为传入的值。
如果传入的参数为 Promise对象,则参数的结果决定了 resolve 的状态和结果 【即实例对象的状态和结果】
// 如果传入的参数为 非Promise 类型的对象,则返回的结果为成功 promise,结果为传入的值。
let p1 = Promise.resolve(521);
console.log(p1); //Promise {<fulfilled>: 521}
// 如果传入的参数为 Promise对象,则参数的结果决定了 resolve 的状态和结果 【即实例对象的状态和结果】
let p2 = Promise.resolve(new Promise((resolve, reject) => {
// resolve('ok');
reject('error');
}))
// console.log(p2); //成功时: Promise {<fulfilled>: 'ok'}
console.log(p2); //失败时: Promise {<rejected>: 'error'}
let re = p2.catch((reason) => {
console.log(reason); //error
})
console.log(re); //Promise {<fulfilled>: undefined}
1.3.5 Promise.reject 方法: Promise.reject(reason)
(1) reason:失败的原因
说明:返回一个失败的 promise 对象,PromiseResult为输入的 reason
let p1 = Promise.reject(521);
let p2 = Promise.reject('12');
let p3 = Promise.reject(new Promise((resolve, reject) => {
resolve('ok');
}))
console.log(p1); // Promise {<rejected>: 521}
console.log(p2); // Promise {<rejected>: '12'}
console.log(p3); // Promise {<rejected>: Promise}
1.3.6 Promise.all 方法: Promise.all(promise)
(1) promise:包含n个 promise的数组
说明:返回一个新的promise,所有的 promise 都成功才成功,只要有一个失败就是直接失败。
let p1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('ok');
}, 1000);
})
// let p2 = Promise.resolve('Success');
let p2 = Promise.reject('error');
let p3 = Promise.resolve('Oh Yeah');
const result = Promise.all([p1, p2, p3]);
console.log(result);
1.3.7 Promise.race 方法: Promise.race(promise)
(1) promise:包含n个 promise的数组
说明:返回一个新的promise,第一个完成的 promise 的结果状态就是最终的结果状态。无论是成功还是失败的结果。
let p1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('ok');
}, 100);
})
let p2 = Promise.resolve('success');
let p3 = Promise.resolve('Oh Yeah');
const result = Promise.race([p1, p2, p3]);
// 哪个先返回,就是哪个,只要一个失败
console.log(result); //success
1.4 promise 的几个关键问题
1.4.1 如何改变 promise 的状态?
(1) resolve(value): 如果当前是 pending就会变为 resolved
(2) reject(reason): 如果当前是 pending就会变为 rejected
(3) 抛出异常:如果当前是 pending就会变为 rejected
let p = new Promise((resolve, reject) => {
// 1.resolve 函数
// resolve('ok'); // pedding => fufilld(resolved)
// 2.reject 函数
// reject('error'); // pedding => rejected
// 3.抛出错误
throw '出问题了'; // pedding => rejected
})
console.log(p);
1.4.2 一个 promise 指定多个 成功 / 失败 回调函数,都会调用吗?
当 promise 改变为对应状态时都会调用。
let p = new Promise((resolve, reject) => {
resolve('ok');
})
// 指定回调 -1
p.then(value => {
console.log(value); //ok
})
// 指定回调 -2
p.then(value => {
console.log(value); //ok
})
1.4.3 改变 promise 状态和指定回调函数谁先谁后?
(1) 都有可能,正常情况下是先指定回调函数再改变状态,但也可以先改变状态再指定回调。
(2) 如何先改变状态再指定回调?
- 在执行器中直接调用 resolve() / reject()
- 延迟更长时间才调用 then()
(3) 什么时候才能得到数据?
- 如果先指定的回调,那就状态发生改变时,回调函数就会调用,得到数据
- 如果先改变状态,那当指定回调时,回调函数就会调用,得到数据
自己的理解:
改变 promise 状态和指定回调函数谁先谁后
指定回调函数即为声明回调函数
如果 执行器 函数中如同步操作,则先改变状态,在指定回调函数,在指定回调函数
如果 执行器 函数中是异步操作,则先指定回调函数【为同步操作】,等状态改变时,在执行回调函数。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>改变 promise 状态和指定回调函数谁先谁后</title>
</head>
<body>
<script>
// 改变 promise 状态和指定回调函数谁先谁后
// 指定回调函数即为声明回调函数
// 如果 执行器 函数中如同步操作,则先改变状态,在指定回调函数,在指定回调函数
// 如果 执行器 函数中是异步操作,则先指定回调函数【为同步操作】,等状态改变时,在执行回调函数。
let p = new Promise((resolve, reject) => {
console.log(444);
setTimeout(() => {
resolve('ok')
}, 0);
})
console.log(111);
setTimeout(() => {
console.log(555);
setTimeout(() => {
console.log(`5555-setTimeout`)
}, 0);
p.then(() => { console.log(`5555-then`) });
}, 0);
p.then((value) => {
console.log(222);
}, (reason) => {
})
setTimeout(() => {
console.log(666);
}, 0);
console.log(333);
// 输出顺序为 444 111 333 222 555 666
// 分析:执行器函数是同步操作,更改状态时异步操作,所以先指定回调函数,等状态状态,在执行回调函数。
// 整体结果分析:
// 执行顺序: 先执行同步操作 --> 在执行异步的微任务 --> 异步的宏任务 --> 微任务 --> 宏任务
</script>
</body>
</html>
代码执行顺序:同步操作 ==》 异步的微任务【如then()】 ==》 异步的宏任务 ==》异步微任务 ==》 异步微任务
注意:放入事件循环的顺序,先放先执行。
1.4.4 promise.then() 返回的新的 promise 的结果状态由什么决定?
(1) 简单表达:由 then() 指定的回调函数执行的结果决定
(2) 详细表达:
- 如果抛出异常,新的 promise 变为 rejected, reason 为抛出的异常。
- 如果返回的是非promise的任意值,新的promise变为 resolved【fulfilled】,value为返回的值。
- 如果返回的是另一个新的promise,此promise的结果就会成为新的 promise 的结果。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>then方法的返回结果由什么决定</title>
</head>
<body>
<script>
let p = new Promise((resolve, reject) => {
resolve('ok');
})
// 执行 then 方法
let result = p.then(value => {
console.log(value);
// 1.抛出错误
// throw '出了问题';
// 2.返回结果是 非 Promise 类型对象
// return 522;
// 3.返回结果是 Promise 对象
return new Promise((resolve, reject) => {
// resolve('success');
reject('error');
})
}, reason => {
console.warn(reason);
})
// 1.抛出错误
// console.log(result); // rejected 出了问题
// 2.返回结果是 非 Promise 类型对象
// console.log(result); // fulfilled 522
// 3.返回结果是 Promise 对象 成功时
// console.log(result); // fulfilled 522
// 3.返回结果是 Promise 对象 成功时
console.log(result); // rejected error
</script>
</body>
</html>
1.4.5 promise 如何串连多个操作任务?
(1) promise 的 then() 返回一个新的 promise,可以开成 then() 的链式调用。
(2) 通过 then 的链式调用串连多个 同步/异步 任务。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>如何串联多个任务</title>
</head>
<body>
<script>
let p = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('ok');
}, 1000);
})
p.then(value => {
return new Promise((resolve, reject) => {
resolve('success');
})
}).then(value => {
console.log(value); // success
// return '我指定了返回值'
}).then(value => {
console.log(value); // undefined
// 如果上一步 指定 返回值
// console.log(value); // 我指定了返回值
})
// 打印 undefined 的原因: 第二个then没有指定返回值,即返回undefined
// 如果第二个then指定返回值,就打印返回值
</script>
</body>
</html>
1.4.6 promise 异常传透?
(1) 当使用 promise 的 then 链式调用,可以在最后指定失败的回调。
(2) 前面任何操作出了异常,都会传到最后失败的回调中处理。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>异常穿透</title>
</head>
<body>
<script>
let p = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('ok');
// reject('eror');
}, 1000);
})
p.then(value => {
console.log(111);
throw '失败啊'
}).then(value => {
console.log(222);
}).then(value => {
console.log(333);
}).catch((reason) => {
console.warn(reason);
})
// 只要出错就会执行 catch 方法,所以一般只要在末尾指定失败的回调即可,中间有错也会执行。即为穿透
</script>
</body>
</html>
1.4.7 中断 promise 链?
(1) 当使用 promise 的 then 链式调用时,在中间中断,不再调用后面的回调函数。
(2) 办法:在回调函数中返回一个 pedding 状态的 promise 对象。【有且只有这一种办法】
(3) 注意:失败的reject() 和 抛出异常的办法都不行,会调用 catch 回调函数。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>如何中断Promise链条</title>
</head>
<body>
<script>
let p = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('ok');
}, 1000);
})
p.then(value => {
console.log(111);
// 有且只有这一种办法
// return 一个 状态为pedding的 promise 对象
return new Promise(() => { });
}).then(value => {
console.log(222);
}).then(value => {
console.log(333);
}).catch((reason) => {
console.warn(reason);
})
// 如果是抛出异常 和 执行reject()函数 是会执行catch回调函数,并不能中断promise链条。
// 只有 return 一个 处于pending状态的 promise 才会中断
</script>
</body>
</html>
二、自定义(手写)Promise
2.1 定义整体机构
// 初始化搭建
function Promise() {
}
// 添加then方法
Promise.prototype.then = function (onResolved, onRejected) {
}
2.2 执行器函数的 两个参数 resolve 和 reject 改变状态的函数结构搭建
// 初始化搭建
function Promise(executor) {
// resolve 函数
function resolve(data) {
}
// reject 函数
function reject(data) {
}
// 同步调用 【执行器函数】
executor(resolve, reject);
}
// 添加then方法
Promise.prototype.then = function (onResolved, onRejected) {
}
2.3 resolve 和 reject 代码实现
// 初始化搭建
function Promise(executor) {
// 添加属性
this.promiseStatus = "pending";
this.promiseResult = null;
// 保存实例对象的 this 的值
const self = this; // 一般用 self _this that
// resolve 函数
function resolve(data) {
// 1.修改对象的状态(promiseStatus)
self.promiseStatus = 'fulfiied';
// 2.设置对象结果的值(promiseResult)
self.promiseResult = data;
}
// reject 函数
function reject(data) {
// 1.修改对象的状态(promiseStatus)
self.promiseStatus = 'rejected';
// 2.设置对象结果的值(promiseResult)
self.promiseResult = data;
}
// 同步调用 【执行器函数】
executor(resolve, reject);
}
// 添加then方法
Promise.prototype.then = function (onResolved, onRejected) {
}
2.4 throw 抛出异常改变状态
使用 try catch 捕获抛出的异常
// 初始化搭建
function Promise(executor) {
// 添加属性
this.promiseStatus = "pending";
this.promiseResult = null;
// 保存实例对象的 this 的值
const self = this; // 一般用 self _this that
// resolve 函数
function resolve(data) {
// 1.修改对象的状态(promiseStatus)
self.promiseStatus = 'fulfiied';
// 2.设置对象结果的值(promiseResult)
self.promiseResult = data;
}
// reject 函数
function reject(data) {
// 1.修改对象的状态(promiseStatus)
self.promiseStatus = 'rejected';
// 2.设置对象结果的值(promiseResult)
self.promiseResult = data;
}
try {
// 同步调用 【执行器函数】
executor(resolve, reject);
} catch (error) {
reject(error);
}
}
// 添加then方法
Promise.prototype.then = function (onResolved, onRejected) {
}
2.5 状态只能修改一次
即:状态不为 pending 就不能执行函数,需要return 出去。
// 初始化搭建
function Promise(executor) {
// 添加属性
this.promiseStatus = "pending";
this.promiseResult = null;
// 保存实例对象的 this 的值
const self = this; // 一般用 self _this that
// resolve 函数
function resolve(data) {
// 判断状态,只能修改一次,即不为pending,就不能执行。
if (self.promiseStatus !== "pending") { return }
// 1.修改对象的状态(promiseStatus)
self.promiseStatus = 'fulfiied';
// 2.设置对象结果的值(promiseResult)
self.promiseResult = data;
}
// reject 函数
function reject(data) {
// 判断状态,只能修改一次,即不为pending,就不能执行。
if (self.promiseStatus !== "pending") { return }
// 1.修改对象的状态(promiseStatus)
self.promiseStatus = 'rejected';
// 2.设置对象结果的值(promiseResult)
self.promiseResult = data;
}
try {
// 同步调用 【执行器函数】
executor(resolve, reject);
} catch (error) {
reject(error);
}
}
// 添加then方法
Promise.prototype.then = function (onResolved, onRejected) {
}
2.6 then方法执行回调
根据对象当前的状态,判断执行 成功的回调函数还是失败的回调函数。
回调函数穿的参数为对象结果的值。
// 初始化搭建
function Promise(executor) {
// 添加属性
this.promiseStatus = "pending";
this.promiseResult = null;
// 保存实例对象的 this 的值
const self = this; // 一般用 self _this that
// resolve 函数
function resolve(data) {
// 判断状态,只能修改一次,即不为pending,就不能执行。
if (self.promiseStatus !== "pending") { return }
// 1.修改对象的状态(promiseStatus)
self.promiseStatus = 'fulfiied';
// 2.设置对象结果的值(promiseResult)
self.promiseResult = data;
}
// reject 函数
function reject(data) {
// 判断状态,只能修改一次,即不为pending,就不能执行。
if (self.promiseStatus !== "pending") { return }
// 1.修改对象的状态(promiseStatus)
self.promiseStatus = 'rejected';
// 2.设置对象结果的值(promiseResult)
self.promiseResult = data;
}
try {
// 同步调用 【执行器函数】
executor(resolve, reject);
} catch (error) {
reject(error);
}
}
// 添加then方法
Promise.prototype.then = function (onResolved, onRejected) {
// 调用回调函数 根据对象的状态判断
if (this.promiseStatus === "fulfiied") {
onResolved(this.promiseResult);
}
if (this.promiseStatus === "rejected") {
onRejected(this.promiseResult);
}
}
2.7 异步任务 then 方法实现
当异步改变执行改变状态的 resolve 和 reject 时,需要改变之后才去执行then方法。
方法:当状态为pending时已经执行then方法,就将回调函数存起来,在发状态改变之后去调回调函数。
// 初始化搭建
function Promise(executor) {
// 添加属性
this.promiseStatus = "pending";
this.promiseResult = null;
// 声明属性
this.callback = {};
// 保存实例对象的 this 的值
const self = this; // 一般用 self _this that
// resolve 函数
function resolve(data) {
// 判断状态,只能修改一次,即不为pending,就不能执行。
if (self.promiseStatus !== "pending") { return }
// 1.修改对象的状态(promiseStatus)
self.promiseStatus = 'fulfiied';
// 2.设置对象结果的值(promiseResult)
self.promiseResult = data;
// 调用成功的回调函数
if (self.callback.onResolved) {
self.callback.onResolved(data);
}
}
// reject 函数
function reject(data) {
// 判断状态,只能修改一次,即不为pending,就不能执行。
if (self.promiseStatus !== "pending") { return }
// 1.修改对象的状态(promiseStatus)
self.promiseStatus = 'rejected';
// 2.设置对象结果的值(promiseResult)
self.promiseResult = data;
// 调用成功的回调函数
if (self.callback.onRejected) {
self.callback.onRejected(data);
}
}
try {
// 同步调用 【执行器函数】
executor(resolve, reject);
} catch (error) {
reject(error);
}
}
// 添加then方法
Promise.prototype.then = function (onResolved, onRejected) {
// 调用回调函数 根据对象的状态判断
if (this.promiseStatus === "fulfiied") {
onResolved(this.promiseResult);
}
if (this.promiseStatus === "rejected") {
onRejected(this.promiseResult);
}
// 状态三种,判断为pending的时候
if (this.promiseStatus === "pending") {
this.callback = {
onResolved: onResolved,
onRejected: onRejected
}
}
}
2.8 指定多个回调函数
当指定多个回调函数时,发现只能执行一次,因为:只保存了一次的回调函数,后面的会覆盖前面的。
解决办法:需要将所有的回调函数都保存起来,等到状态改变再去调用回调函数。
1、将之前的存回调函数的属性 callback改为数组。
2、在保存是使用push保存,调用时循环调用callback中的回调函数。
// 初始化搭建
function Promise(executor) {
// 添加属性
this.promiseStatus = "pending";
this.promiseResult = null;
// 声明属性
this.callback = [];
// 保存实例对象的 this 的值
const self = this; // 一般用 self _this that
// resolve 函数
function resolve(data) {
// 判断状态,只能修改一次,即不为pending,就不能执行。
if (self.promiseStatus !== "pending") { return }
// 1.修改对象的状态(promiseStatus)
self.promiseStatus = 'fulfiied';
// 2.设置对象结果的值(promiseResult)
self.promiseResult = data;
// 调用成功的回调函数
self.callback.forEach(item => {
item.onResolved(data);
});
}
// reject 函数
function reject(data) {
// 判断状态,只能修改一次,即不为pending,就不能执行。
if (self.promiseStatus !== "pending") { return }
// 1.修改对象的状态(promiseStatus)
self.promiseStatus = 'rejected';
// 2.设置对象结果的值(promiseResult)
self.promiseResult = data;
// 调用成功的回调函数
self.callback.forEach(item => {
item.onRejected(data);
});
}
try {
// 同步调用 【执行器函数】
executor(resolve, reject);
} catch (error) {
reject(error);
}
}
// 添加then方法
Promise.prototype.then = function (onResolved, onRejected) {
// 调用回调函数 根据对象的状态判断
if (this.promiseStatus === "fulfiied") {
onResolved(this.promiseResult);
}
if (this.promiseStatus === "rejected") {
onRejected(this.promiseResult);
}
// 状态三种,判断为pending的时候
if (this.promiseStatus === "pending") {
// 保存回调函数
this.callback.push({
onResolved: onResolved,
onRejected: onRejected
})
}
}
2.9 同步任务 then 返回结果
then方法的返回结果是一个undefined,但是需要返回一个promise对象,并指定结果。
根据之前的阐述的不同情况来完成。
1.返回是一个非promise
2.返回是一个promise
3.对抛出异常的捕获
// 初始化搭建
function Promise(executor) {
// 添加属性
this.promiseStatus = "pending";
this.promiseResult = null;
// 声明属性
this.callback = [];
// 保存实例对象的 this 的值
const self = this; // 一般用 self _this that
// resolve 函数
function resolve(data) {
// 判断状态,只能修改一次,即不为pending,就不能执行。
if (self.promiseStatus !== "pending") { return }
// 1.修改对象的状态(promiseStatus)
self.promiseStatus = 'fulfiied';
// 2.设置对象结果的值(promiseResult)
self.promiseResult = data;
// 调用成功的回调函数
self.callback.forEach(item => {
item.onResolved(data);
});
}
// reject 函数
function reject(data) {
// 判断状态,只能修改一次,即不为pending,就不能执行。
if (self.promiseStatus !== "pending") { return }
// 1.修改对象的状态(promiseStatus)
self.promiseStatus = 'rejected';
// 2.设置对象结果的值(promiseResult)
self.promiseResult = data;
// 调用成功的回调函数
self.callback.forEach(item => {
item.onRejected(data);
});
}
try {
// 同步调用 【执行器函数】
executor(resolve, reject);
} catch (error) {
reject(error);
}
}
// 添加then方法
Promise.prototype.then = function (onResolved, onRejected) {
return new Promise((resolve, reject) => {
// 调用回调函数 根据对象的状态判断
if (this.promiseStatus === "fulfiied") {
try {
// 获取回调函数的执行结果
let result = onResolved(this.promiseResult);
if (result instanceof Promise) {
// 如果是一个promise
result.then((v) => {
resolve(v);
}, (r) => {
reject(r);
})
} else {
// 结果的状态为 【成功】
resolve(result);
}
} catch (error) {
reject(error)
}
}
if (this.promiseStatus === "rejected") {
try {
// 获取回调函数的执行结果
let result = onRejected(this.promiseResult);
if (result instanceof Promise) {
// 如果是一个promise
result.then((v) => {
resolve(v);
}, (r) => {
reject(r);
})
} else {
// 结果的状态为 【成功】
resolve(result);
}
} catch (error) {
reject(error)
}
}
// 状态三种,判断为pending的时候
if (this.promiseStatus === "pending") {
// 保存回调函数
this.callback.push({
onResolved: onResolved,
onRejected: onRejected
})
}
})
}
2.10 异步任务 then 返回结果
异步的时候,没有调返回的promise对象,导致状态一直为pending,结果为undefined。
解决办法:为pending时,改变状态的函数是在Promise中的resolve或reject调的,执行的是保存的回调函数。适配保存时的回调函数。
重复代码过多,封装一个函数。callback(type)
此文件为一个完成的then方法实现。 但是没有考虑then只有一个参数或者没有参数的情况。
// 初始化搭建
function Promise(executor) {
// 添加属性
this.promiseStatus = "pending";
this.promiseResult = null;
// 声明属性
this.callback = [];
// 保存实例对象的 this 的值
const self = this; // 一般用 self _this that
// resolve 函数
function resolve(data) {
// 判断状态,只能修改一次,即不为pending,就不能执行。
if (self.promiseStatus !== "pending") { return }
// 1.修改对象的状态(promiseStatus)
self.promiseStatus = 'fulfiied';
// 2.设置对象结果的值(promiseResult)
self.promiseResult = data;
// 调用成功的回调函数
self.callback.forEach(item => {
item.onResolved(data);
});
}
// reject 函数
function reject(data) {
// 判断状态,只能修改一次,即不为pending,就不能执行。
if (self.promiseStatus !== "pending") { return }
// 1.修改对象的状态(promiseStatus)
self.promiseStatus = 'rejected';
// 2.设置对象结果的值(promiseResult)
self.promiseResult = data;
// 调用成功的回调函数
self.callback.forEach(item => {
item.onRejected(data);
});
}
try {
// 同步调用 【执行器函数】
executor(resolve, reject);
} catch (error) {
reject(error);
}
}
// 添加then方法
Promise.prototype.then = function (onResolved, onRejected) {
const self = this;
return new Promise((resolve, reject) => {
// 重复代码太多,封装函数
function callback(type) {
try {
// 获取回调函数的执行结果
let result = type(self.promiseResult);
if (result instanceof Promise) {
// 如果是一个promise
result.then((v) => {
resolve(v);
}, (r) => {
reject(r);
})
} else {
// 结果的状态为 【成功】
resolve(result);
}
} catch (error) {
reject(error)
}
}
// 调用回调函数 根据对象的状态判断
if (this.promiseStatus === "fulfiied") {
callback(onResolved);
}
if (this.promiseStatus === "rejected") {
callback(onRejected);
}
// 状态三种,判断为pending的时候
if (this.promiseStatus === "pending") {
// 保存回调函数
this.callback.push({
onResolved: function () {
callback(onResolved);
},
onRejected: function () {
callback(onRejected);
},
})
}
})
}
2.11 catch 方法与异常穿透
调用then方法来完成,第一个参数可以传一个undefined。
注意:在then方法中需要判断,参数为空时的操作。
// 初始化搭建
function Promise(executor) {
// 添加属性
this.promiseStatus = "pending";
this.promiseResult = null;
// 声明属性
this.callback = [];
// 保存实例对象的 this 的值
const self = this; // 一般用 self _this that
// resolve 函数
function resolve(data) {
// 判断状态,只能修改一次,即不为pending,就不能执行。
if (self.promiseStatus !== "pending") { return }
// 1.修改对象的状态(promiseStatus)
self.promiseStatus = 'fulfiied';
// 2.设置对象结果的值(promiseResult)
self.promiseResult = data;
// 调用成功的回调函数
self.callback.forEach(item => {
item.onResolved(data);
});
}
// reject 函数
function reject(data) {
// 判断状态,只能修改一次,即不为pending,就不能执行。
if (self.promiseStatus !== "pending") { return }
// 1.修改对象的状态(promiseStatus)
self.promiseStatus = 'rejected';
// 2.设置对象结果的值(promiseResult)
self.promiseResult = data;
// 调用成功的回调函数
self.callback.forEach(item => {
item.onRejected(data);
});
}
try {
// 同步调用 【执行器函数】
executor(resolve, reject);
} catch (error) {
reject(error);
}
}
// 添加then方法
Promise.prototype.then = function (onResolved, onRejected) {
const self = this;
// 判断 回调函数参数
if (typeof onRejected !== 'function') {
onRejected = reason => {
throw reason;
}
}
if (typeof onResolved !== 'function') {
onResolved = value => value
}
return new Promise((resolve, reject) => {
// 重复代码太多,封装函数
function callback(type) {
try {
// 获取回调函数的执行结果
let result = type(self.promiseResult);
if (result instanceof Promise) {
// 如果是一个promise
result.then((v) => {
resolve(v);
}, (r) => {
reject(r);
})
} else {
// 结果的状态为 【成功】
resolve(result);
}
} catch (error) {
reject(error)
}
}
// 调用回调函数 根据对象的状态判断
if (this.promiseStatus === "fulfiied") {
callback(onResolved);
}
if (this.promiseStatus === "rejected") {
callback(onRejected);
}
// 状态三种,判断为pending的时候
if (this.promiseStatus === "pending") {
// 保存回调函数
this.callback.push({
onResolved: function () {
callback(onResolved);
},
onRejected: function () {
callback(onRejected);
},
})
}
})
}
// 添加catch方法
Promise.prototype.catch = function (onRejected) {
return this.then(undefined, onRejected);
}
2.12 Promise.resolve 封装
分两种情况
1.参数为promise
2.参数为非promise
// 初始化搭建
function Promise(executor) {
// 添加属性
this.promiseStatus = "pending";
this.promiseResult = null;
// 声明属性
this.callback = [];
// 保存实例对象的 this 的值
const self = this; // 一般用 self _this that
// resolve 函数
function resolve(data) {
// 判断状态,只能修改一次,即不为pending,就不能执行。
if (self.promiseStatus !== "pending") { return }
// 1.修改对象的状态(promiseStatus)
self.promiseStatus = 'fulfiied';
// 2.设置对象结果的值(promiseResult)
self.promiseResult = data;
// 调用成功的回调函数
self.callback.forEach(item => {
item.onResolved(data);
});
}
// reject 函数
function reject(data) {
// 判断状态,只能修改一次,即不为pending,就不能执行。
if (self.promiseStatus !== "pending") { return }
// 1.修改对象的状态(promiseStatus)
self.promiseStatus = 'rejected';
// 2.设置对象结果的值(promiseResult)
self.promiseResult = data;
// 调用成功的回调函数
self.callback.forEach(item => {
item.onRejected(data);
});
}
try {
// 同步调用 【执行器函数】
executor(resolve, reject);
} catch (error) {
reject(error);
}
}
// 添加then方法
Promise.prototype.then = function (onResolved, onRejected) {
const self = this;
// 判断 回调函数参数
if (typeof onRejected !== 'function') {
onRejected = reason => {
throw reason;
}
}
if (typeof onResolved !== 'function') {
onResolved = value => value
}
return new Promise((resolve, reject) => {
// 重复代码太多,封装函数
function callback(type) {
try {
// 获取回调函数的执行结果
let result = type(self.promiseResult);
if (result instanceof Promise) {
// 如果是一个promise
result.then((v) => {
resolve(v);
}, (r) => {
reject(r);
})
} else {
// 结果的状态为 【成功】
resolve(result);
}
} catch (error) {
reject(error)
}
}
// 调用回调函数 根据对象的状态判断
if (this.promiseStatus === "fulfiied") {
callback(onResolved);
}
if (this.promiseStatus === "rejected") {
callback(onRejected);
}
// 状态三种,判断为pending的时候
if (this.promiseStatus === "pending") {
// 保存回调函数
this.callback.push({
onResolved: function () {
callback(onResolved);
},
onRejected: function () {
callback(onRejected);
},
})
}
})
}
// 添加catch方法
Promise.prototype.catch = function (onRejected) {
return this.then(undefined, onRejected);
}
// 添加 resolve 方法
Promise.resolve = function (value) {
// 返回 promise 对象
return new Promise((resolve, reject) => {
if (value instanceof Promise) {
value.then((v) => {
resolve(v);
}, (r) => {
reject(r);
})
} else {
resolve(value);
}
})
}
2.13 Promise.reject 封装
无论参数为什么,都返回一个失败的promise对象。
// 初始化搭建
function Promise(executor) {
// 添加属性
this.promiseStatus = "pending";
this.promiseResult = null;
// 声明属性
this.callback = [];
// 保存实例对象的 this 的值
const self = this; // 一般用 self _this that
// resolve 函数
function resolve(data) {
// 判断状态,只能修改一次,即不为pending,就不能执行。
if (self.promiseStatus !== "pending") { return }
// 1.修改对象的状态(promiseStatus)
self.promiseStatus = 'fulfiied';
// 2.设置对象结果的值(promiseResult)
self.promiseResult = data;
// 调用成功的回调函数
self.callback.forEach(item => {
item.onResolved(data);
});
}
// reject 函数
function reject(data) {
// 判断状态,只能修改一次,即不为pending,就不能执行。
if (self.promiseStatus !== "pending") { return }
// 1.修改对象的状态(promiseStatus)
self.promiseStatus = 'rejected';
// 2.设置对象结果的值(promiseResult)
self.promiseResult = data;
// 调用成功的回调函数
self.callback.forEach(item => {
item.onRejected(data);
});
}
try {
// 同步调用 【执行器函数】
executor(resolve, reject);
} catch (error) {
reject(error);
}
}
// 添加then方法
Promise.prototype.then = function (onResolved, onRejected) {
const self = this;
// 判断 回调函数参数
if (typeof onRejected !== 'function') {
onRejected = reason => {
throw reason;
}
}
if (typeof onResolved !== 'function') {
onResolved = value => value
}
return new Promise((resolve, reject) => {
// 重复代码太多,封装函数
function callback(type) {
try {
// 获取回调函数的执行结果
let result = type(self.promiseResult);
if (result instanceof Promise) {
// 如果是一个promise
result.then((v) => {
resolve(v);
}, (r) => {
reject(r);
})
} else {
// 结果的状态为 【成功】
resolve(result);
}
} catch (error) {
reject(error)
}
}
// 调用回调函数 根据对象的状态判断
if (this.promiseStatus === "fulfiied") {
callback(onResolved);
}
if (this.promiseStatus === "rejected") {
callback(onRejected);
}
// 状态三种,判断为pending的时候
if (this.promiseStatus === "pending") {
// 保存回调函数
this.callback.push({
onResolved: function () {
callback(onResolved);
},
onRejected: function () {
callback(onRejected);
},
})
}
})
}
// 添加catch方法
Promise.prototype.catch = function (onRejected) {
return this.then(undefined, onRejected);
}
// 添加 resolve 方法
Promise.resolve = function (value) {
// 返回 promise 对象
return new Promise((resolve, reject) => {
if (value instanceof Promise) {
value.then((v) => {
resolve(v);
}, (r) => {
reject(r);
})
} else {
resolve(value);
}
})
}
// 添加 reject 方法
Promise.reject = function (reason) {
return new Promise((resolve, reject) => {
reject(reason);
})
}
2.14 Promise.all 封装
只要一个失败就返回一个失败的promise对象,状态和值为失败的promise的状态和值。
循环遍历执行每一个promise对象的then,成功回调就将值放在数组对应顺序下。
成功的数和传入的数组长度一致时,就证明结束。
// 初始化搭建
function Promise(executor) {
// 添加属性
this.promiseStatus = "pending";
this.promiseResult = null;
// 声明属性
this.callback = [];
// 保存实例对象的 this 的值
const self = this; // 一般用 self _this that
// resolve 函数
function resolve(data) {
// 判断状态,只能修改一次,即不为pending,就不能执行。
if (self.promiseStatus !== "pending") { return }
// 1.修改对象的状态(promiseStatus)
self.promiseStatus = 'fulfiied';
// 2.设置对象结果的值(promiseResult)
self.promiseResult = data;
// 调用成功的回调函数
self.callback.forEach(item => {
item.onResolved(data);
});
}
// reject 函数
function reject(data) {
// 判断状态,只能修改一次,即不为pending,就不能执行。
if (self.promiseStatus !== "pending") { return }
// 1.修改对象的状态(promiseStatus)
self.promiseStatus = 'rejected';
// 2.设置对象结果的值(promiseResult)
self.promiseResult = data;
// 调用成功的回调函数
self.callback.forEach(item => {
item.onRejected(data);
});
}
try {
// 同步调用 【执行器函数】
executor(resolve, reject);
} catch (error) {
reject(error);
}
}
// 添加then方法
Promise.prototype.then = function (onResolved, onRejected) {
const self = this;
// 判断 回调函数参数
if (typeof onRejected !== 'function') {
onRejected = reason => {
throw reason;
}
}
if (typeof onResolved !== 'function') {
onResolved = value => value
}
return new Promise((resolve, reject) => {
// 重复代码太多,封装函数
function callback(type) {
try {
// 获取回调函数的执行结果
let result = type(self.promiseResult);
if (result instanceof Promise) {
// 如果是一个promise
result.then((v) => {
resolve(v);
}, (r) => {
reject(r);
})
} else {
// 结果的状态为 【成功】
resolve(result);
}
} catch (error) {
reject(error)
}
}
// 调用回调函数 根据对象的状态判断
if (this.promiseStatus === "fulfiied") {
callback(onResolved);
}
if (this.promiseStatus === "rejected") {
callback(onRejected);
}
// 状态三种,判断为pending的时候
if (this.promiseStatus === "pending") {
// 保存回调函数
this.callback.push({
onResolved: function () {
callback(onResolved);
},
onRejected: function () {
callback(onRejected);
},
})
}
})
}
// 添加catch方法
Promise.prototype.catch = function (onRejected) {
return this.then(undefined, onRejected);
}
// 添加 resolve 方法
Promise.resolve = function (value) {
// 返回 promise 对象
return new Promise((resolve, reject) => {
if (value instanceof Promise) {
value.then((v) => {
resolve(v);
}, (r) => {
reject(r);
})
} else {
resolve(value);
}
})
}
// 添加 reject 方法
Promise.reject = function (reason) {
return new Promise((resolve, reject) => {
reject(reason);
})
}
// 添加 all 方法
Promise.all = function (promises) {
return new Promise((resolve, reject) => {
// 声明变量
let count = 0;
let arr = [];
for (let i = 0; i < promises.length; i++) {
promises[i].then(v => {
// 得知对象的状态是成功
// 每个promise对象都成功
count++;
// 将当前promise对象成功的结果,存入数组
// 并且需要按照顺序存入数组
arr[i] = v;
// 判断
if (count === promises.length) {
// 修改状态
resolve(arr);
}
}, r => {
reject(r);
})
}
})
}
2.15 Promise.race 封装
哪个第一个返回,哪个就是结果。
// 初始化搭建
function Promise(executor) {
// 添加属性
this.promiseStatus = "pending";
this.promiseResult = null;
// 声明属性
this.callback = [];
// 保存实例对象的 this 的值
const self = this; // 一般用 self _this that
// resolve 函数
function resolve(data) {
// 判断状态,只能修改一次,即不为pending,就不能执行。
if (self.promiseStatus !== "pending") { return }
// 1.修改对象的状态(promiseStatus)
self.promiseStatus = 'fulfiied';
// 2.设置对象结果的值(promiseResult)
self.promiseResult = data;
// 调用成功的回调函数
self.callback.forEach(item => {
item.onResolved(data);
});
}
// reject 函数
function reject(data) {
// 判断状态,只能修改一次,即不为pending,就不能执行。
if (self.promiseStatus !== "pending") { return }
// 1.修改对象的状态(promiseStatus)
self.promiseStatus = 'rejected';
// 2.设置对象结果的值(promiseResult)
self.promiseResult = data;
// 调用成功的回调函数
self.callback.forEach(item => {
item.onRejected(data);
});
}
try {
// 同步调用 【执行器函数】
executor(resolve, reject);
} catch (error) {
reject(error);
}
}
// 添加then方法
Promise.prototype.then = function (onResolved, onRejected) {
const self = this;
// 判断 回调函数参数
if (typeof onRejected !== 'function') {
onRejected = reason => {
throw reason;
}
}
if (typeof onResolved !== 'function') {
onResolved = value => value
}
return new Promise((resolve, reject) => {
// 重复代码太多,封装函数
function callback(type) {
try {
// 获取回调函数的执行结果
let result = type(self.promiseResult);
if (result instanceof Promise) {
// 如果是一个promise
result.then((v) => {
resolve(v);
}, (r) => {
reject(r);
})
} else {
// 结果的状态为 【成功】
resolve(result);
}
} catch (error) {
reject(error)
}
}
// 调用回调函数 根据对象的状态判断
if (this.promiseStatus === "fulfiied") {
callback(onResolved);
}
if (this.promiseStatus === "rejected") {
callback(onRejected);
}
// 状态三种,判断为pending的时候
if (this.promiseStatus === "pending") {
// 保存回调函数
this.callback.push({
onResolved: function () {
callback(onResolved);
},
onRejected: function () {
callback(onRejected);
},
})
}
})
}
// 添加catch方法
Promise.prototype.catch = function (onRejected) {
return this.then(undefined, onRejected);
}
// 添加 resolve 方法
Promise.resolve = function (value) {
// 返回 promise 对象
return new Promise((resolve, reject) => {
if (value instanceof Promise) {
value.then((v) => {
resolve(v);
}, (r) => {
reject(r);
})
} else {
resolve(value);
}
})
}
// 添加 reject 方法
Promise.reject = function (reason) {
return new Promise((resolve, reject) => {
reject(reason);
})
}
// 添加 all 方法
Promise.all = function (promises) {
return new Promise((resolve, reject) => {
// 声明变量
let count = 0;
let arr = [];
for (let i = 0; i < promises.length; i++) {
promises[i].then(v => {
// 得知对象的状态是成功
// 每个promise对象都成功
count++;
// 将当前promise对象成功的结果,存入数组
// 并且需要按照顺序存入数组
arr[i] = v;
// 判断
if (count === promises.length) {
// 修改状态
resolve(arr);
}
}, r => {
reject(r);
})
}
})
}
// 添加 race 方法
Promise.race = function (promises) {
return new Promise((resolve, reject) => {
for (let i = 0; i < promises.length; i++) {
promises[i].then(v => {
resolve(v);
}, r => {
reject(r)
})
}
})
}
2.16 回调函数 异步调用
目前情况下,回调函数是同步执行的。按照正常的方式,then是微任务,需要先等待,同步任务执行完之后,才会执行。
2.16.1 完整版1.0
// 初始化搭建
function Promise(executor) {
// 添加属性
this.promiseStatus = "pending";
this.promiseResult = null;
// 声明属性
this.callback = [];
// 保存实例对象的 this 的值
const self = this; // 一般用 self _this that
// resolve 函数
function resolve(data) {
// 判断状态,只能修改一次,即不为pending,就不能执行。
if (self.promiseStatus !== "pending") { return }
// 1.修改对象的状态(promiseStatus)
self.promiseStatus = 'fulfiied';
// 2.设置对象结果的值(promiseResult)
self.promiseResult = data;
// 调用成功的回调函数
setTimeout(() => {
self.callback.forEach(item => {
item.onResolved(data);
});
});
}
// reject 函数
function reject(data) {
// 判断状态,只能修改一次,即不为pending,就不能执行。
if (self.promiseStatus !== "pending") { return }
// 1.修改对象的状态(promiseStatus)
self.promiseStatus = 'rejected';
// 2.设置对象结果的值(promiseResult)
self.promiseResult = data;
// 调用成功的回调函数
setTimeout(() => {
self.callback.forEach(item => {
item.onRejected(data);
});
});
}
try {
// 同步调用 【执行器函数】
executor(resolve, reject);
} catch (error) {
reject(error);
}
}
// 添加then方法
Promise.prototype.then = function (onResolved, onRejected) {
const self = this;
// 判断 回调函数参数
if (typeof onRejected !== 'function') {
onRejected = reason => {
throw reason;
}
}
if (typeof onResolved !== 'function') {
onResolved = value => value
}
return new Promise((resolve, reject) => {
// 重复代码太多,封装函数
function callback(type) {
try {
// 获取回调函数的执行结果
let result = type(self.promiseResult);
if (result instanceof Promise) {
// 如果是一个promise
result.then((v) => {
resolve(v);
}, (r) => {
reject(r);
})
} else {
// 结果的状态为 【成功】
resolve(result);
}
} catch (error) {
reject(error)
}
}
// 调用回调函数 根据对象的状态判断
if (this.promiseStatus === "fulfiied") {
setTimeout(() => {
callback(onResolved)
});
}
if (this.promiseStatus === "rejected") {
setTimeout(() => {
callback(onRejected)
});
}
// 状态三种,判断为pending的时候
if (this.promiseStatus === "pending") {
// 保存回调函数
this.callback.push({
onResolved: function () {
callback(onResolved);
},
onRejected: function () {
callback(onRejected);
},
})
}
})
}
// 添加catch方法
Promise.prototype.catch = function (onRejected) {
return this.then(undefined, onRejected);
}
// 添加 resolve 方法
Promise.resolve = function (value) {
// 返回 promise 对象
return new Promise((resolve, reject) => {
if (value instanceof Promise) {
value.then((v) => {
resolve(v);
}, (r) => {
reject(r);
})
} else {
resolve(value);
}
})
}
// 添加 reject 方法
Promise.reject = function (reason) {
return new Promise((resolve, reject) => {
reject(reason);
})
}
// 添加 all 方法
Promise.all = function (promises) {
return new Promise((resolve, reject) => {
// 声明变量
let count = 0;
let arr = [];
for (let i = 0; i < promises.length; i++) {
promises[i].then(v => {
// 得知对象的状态是成功
// 每个promise对象都成功
count++;
// 将当前promise对象成功的结果,存入数组
// 并且需要按照顺序存入数组
arr[i] = v;
// 判断
if (count === promises.length) {
// 修改状态
resolve(arr);
}
}, r => {
reject(r);
})
}
})
}
// 添加 race 方法
Promise.race = function (promises) {
return new Promise((resolve, reject) => {
for (let i = 0; i < promises.length; i++) {
promises[i].then(v => {
resolve(v);
}, r => {
reject(r)
})
}
})
}
2.17 class 封装
使用calss封装。
属于实例对象的方法直接添加到类上。
属于类Promise的方法,需要使用 static ,是属于类的静态方法,属于内部。
2.17.1 完整版2.0
class Promise {
// 构造方法
constructor(executor) {
// 添加属性
this.promiseStatus = "pending";
this.promiseResult = null;
// 声明属性
this.callback = [];
// 保存实例对象的 this 的值
const self = this; // 一般用 self _this that
// resolve 函数
function resolve(data) {
// 判断状态,只能修改一次,即不为pending,就不能执行。
if (self.promiseStatus !== "pending") { return }
// 1.修改对象的状态(promiseStatus)
self.promiseStatus = 'fulfiied';
// 2.设置对象结果的值(promiseResult)
self.promiseResult = data;
// 调用成功的回调函数
setTimeout(() => {
self.callback.forEach(item => {
item.onResolved(data);
});
});
}
// reject 函数
function reject(data) {
// 判断状态,只能修改一次,即不为pending,就不能执行。
if (self.promiseStatus !== "pending") { return }
// 1.修改对象的状态(promiseStatus)
self.promiseStatus = 'rejected';
// 2.设置对象结果的值(promiseResult)
self.promiseResult = data;
// 调用成功的回调函数
setTimeout(() => {
self.callback.forEach(item => {
item.onRejected(data);
});
});
}
try {
// 同步调用 【执行器函数】
executor(resolve, reject);
} catch (error) {
reject(error);
}
}
// then 方法
then(onResolved, onRejected) {
const self = this;
// 判断 回调函数参数
if (typeof onRejected !== 'function') {
onRejected = reason => {
throw reason;
}
}
if (typeof onResolved !== 'function') {
onResolved = value => value
}
return new Promise((resolve, reject) => {
// 重复代码太多,封装函数
function callback(type) {
try {
// 获取回调函数的执行结果
let result = type(self.promiseResult);
if (result instanceof Promise) {
// 如果是一个promise
result.then((v) => {
resolve(v);
}, (r) => {
reject(r);
})
} else {
// 结果的状态为 【成功】
resolve(result);
}
} catch (error) {
reject(error)
}
}
// 调用回调函数 根据对象的状态判断
if (this.promiseStatus === "fulfiied") {
setTimeout(() => {
callback(onResolved)
});
}
if (this.promiseStatus === "rejected") {
setTimeout(() => {
callback(onRejected)
});
}
// 状态三种,判断为pending的时候
if (this.promiseStatus === "pending") {
// 保存回调函数
this.callback.push({
onResolved: function () {
callback(onResolved);
},
onRejected: function () {
callback(onRejected);
},
})
}
})
}
// catch 方法
catch(onRejected) {
return this.then(undefined, onRejected);
}
// 添加 resolve 方法
static resolve(value) {
// 返回 promise 对象
return new Promise((resolve, reject) => {
if (value instanceof Promise) {
value.then((v) => {
resolve(v);
}, (r) => {
reject(r);
})
} else {
resolve(value);
}
})
}
// 添加 reject 方法
static reject(reason) {
return new Promise((resolve, reject) => {
reject(reason);
})
}
// 添加 all 方法
static all(promises) {
return new Promise((resolve, reject) => {
// 声明变量
let count = 0;
let arr = [];
for (let i = 0; i < promises.length; i++) {
promises[i].then(v => {
// 得知对象的状态是成功
// 每个promise对象都成功
count++;
// 将当前promise对象成功的结果,存入数组
// 并且需要按照顺序存入数组
arr[i] = v;
// 判断
if (count === promises.length) {
// 修改状态
resolve(arr);
}
}, r => {
reject(r);
})
}
})
}
// 添加 race 方法
static race() {
return new Promise((resolve, reject) => {
for (let i = 0; i < promises.length; i++) {
promises[i].then(v => {
resolve(v);
}, r => {
reject(r)
})
}
})
}
}
三、async 与 await
3.1 mdn 文档
3.2 async 函数
1.函数的返回值为promise对象
2.promise 对象的结果是由 async 函数执行的返回值决定。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>async</title>
</head>
<body>
<script>
async function main() {
// 1.如果返回值是一个非Promise类型的数据
// return 521;
// 2.如果返回的是一个 Promise 对象
// return new Promise((resolve, reject) => {
// // resolve('ok');
// reject('error');
// })
// 3.抛出异常
// throw 'Oh No'
}
let result = main();
console.log(result);
</script>
</body>
</html>
3.3 await 表达式
1. await 右侧的表达式一般为 promise 对象,但也可以是其它的值。
2.如果表达式是 promise 对象,await 返回的是 promise 成功的值。
3.如果表达式是其他的值,直接将此值作为await的返回值。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>await</title>
</head>
<body>
<script>
async function main() {
let p = new Promise((resolve, reject) => {
// resolve('ok');
reject('error');
})
// 1.右侧为promise的情况
// let res = await p;
// 2.右侧为其他类型的数据
let res2 = await 20;
// 3.如果promise失败的状态
try {
let res2 = await p;
} catch (error) {
console.log(error); // error
}
// console.log(res); // ok
console.log(res2); //20
}
main();
</script>
</body>
</html>
3.4 注意
1. await 必须写在 async 函数中,但 async 函数中可以么有 await
2.如果await的promise 失败了,就会抛出异常,需要通过 try .... catch 捕获处理。
3.5 案例
3.5.1nodejs 获取文件内容
const fs = require('fs');
// 之前写法 回调函数的方式
// fs.readFile('./file/1.html', (err, data1) => {
// if (err) throw err;
// fs.readFile('./file/2.html', (err, data2) => {
// if (err) throw err;
// fs.readFile('./file/3.html', (err, data3) => {
// if (err) throw err;
// console.log(data1 + data2 + data3);
// })
// })
// })
// async 与 await
const util = require('util');
// util.promisify(fs.readFile) 将方法返回值为一个promise
const mineReadFile = util.promisify(fs.readFile);
async function main() {
try {
let data1 = await mineReadFile('./file/1.html');
let data2 = await mineReadFile('./file/2.html');
let data3 = await mineReadFile('./file/3.html');
console.log(data1 + data2 + data3);
} catch (error) {
console.log(error);
}
}
main();
3.5.2 async与await结合发送AJAX
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>4-async与await结合发送AJAX</title>
</head>
<body>
<button id="btn">获取段子</button>
<script>
function sendAJAX(url) {
return new Promise((resolve, reject) => {
// 1.创建对象
const xhr = new XMLHttpRequest();
// 指定返回的数据格式
xhr.responseType = 'json';
// 2.初始化
xhr.open('GET', url);
// 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);
}
}
}
})
}
let url = "https://api.apiopen.top/getJoke";
let btn = document.querySelector('#btn');
btn.addEventListener('click', async function () {
let duanzi = await sendAJAX(url);
console.log(duanzi);
})
</script>
</body>
</html>