笔记根据视频与PPT进行整理
【视频链接:尚硅谷Web前端Promise教程从入门到精通】
【视频资源链接–阿里云盘】
【个人代码笔记–阿里云盘】
【视频资源个人代码笔记链接–百度网盘链接】
提取码:1234
字数4.5w+
Promise
- 前言
- 目录
- 1. Promise 简介
- 2. Promise 基本使用
- 2.1 Promise 基本使用体验
- 回调函数实现:
- 基于 Promise 实现:
- 2.2 基于 promise 的形式读取文件
- 回调函数形式实现:
- 基于 Promise 实现:
- 2.3 基于 Promise 的 ajax 请求
- 2.4 基于 Promise 封装 fs 模块读取文件
- 2.5 util.promisify 方法封装转化成 Promise
- 2.6 Promise封装AJAX操作
- 2.7 promise 的状态
- 2.8 promise 的基本流程
- 3. Promise API
- 3.1 Promise 构造函数
- 3.2 Promise.prototype.then 方法
- 3.3 Promise.prototype.catch 方法
- 3.4 Promise.resolve 方法
- 3.5 Promise.reject 方法
- 3.6 Promise.all 方法
- 3.7 Promise.race 方法
- 4. promise 的几个关键问题
- 4.1 如何改变 promise 的状态
- 4.2 一个 promise 指定多个成功/失败回调函数
- 4.3 改变 promise 状态和指定回调函数谁先谁后
- 4.4 promise.then()返回的新 promise 的结果状态
- 4.5 promise 串连多个操作任务(链式调用)
- 4.6 promise 异常传透
- 4.7 中断 promise 链
- 5. 自定义手写实现 Promise
- 5.1 定义整体结构
- 5.2 Promise 构造函数的实现
- 5.2.1 resolve与reject结构搭建
- 5.2.2 resolve与reject函数实现
- 5.2.3 throw抛出错误改变状态
- 5.2.3 状态只能修改一次
- 5.2.4 测试
- 5.2.5 保存实例对象的this
- 5.2.6 再测试
- 5.3 promise.then()的实现
- 5.3.1 then() 实现
- 5.3.2 then() 异步回调执行实现
- 5.3.3 then() 指定多个回调函数
- 5.3.4 同步任务下then()返回结果的实现
- 执行流程图
- 5.3.5 异步任务下then()返回结果的实现
- 5.3.6 then()代码优化
- 5.4 Promise.catch()实现
- 5.4.1 catch()实现
- 5.4.2 异常穿透实现
- 5.4.3 值传递实现
- 5.5 resolve() 实现
- 5.6 reject() 实现
- 5.7 all() 实现
- 5.8 race()实现
- 5.9 then方法回调的异步执行
- 5.10 封装为Promise类
- 6 async与await
- 6.1 mdn 文档
- 6.2 async 函数
- 6.3 await 表达式
- 6.4 async与await结合实践 -- 读取文件
- 6.4.1 不基于Promise实现 -- 回调地狱
- 6.4.2 基于Promise
Promise 是一门新的技术(ES6 规范)
Promise 是 JS 中进行异步编程的新解决方案。(旧方案是单纯使用回调函数)
异步编程:
旧方案中单纯使用回调函数,很可能会出现回调地狱(回调函数嵌套调用, 外部回调函数异步执行的结果是嵌套的回调执行的条件)的问题,不便于阅读,可读性差,不便于异常处理。
回调地狱:
Promise 支持链式调用, 可以解决回调地狱问题
从语法上来说: Promise 是一个构造函数。
从功能上来说: promise 对象用来封装一个异步操作并可以获取其成功/失败的结果值。
实现一个小功能:
点击按钮后显示是否中奖(30%概率中奖),若中奖弹出 “恭喜恭喜, 奖品为 10万 RMB 劳斯莱斯优惠券” ,若未中奖弹出 “再接再厉”。
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>Documenttitle>
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;
}
/**
点击按钮后显示是否中奖(30%概率中奖)
若中奖弹出 恭喜恭喜, 奖品为 10万 RMB 劳斯莱斯优惠券
若未中奖弹出 再接再厉
*/
//获取元素对象
const btn = document.querySelector('#btn');
//绑定单击事件
btn.addEventListener('click', function(){
// 定时器
setTimeout(() => {
//30% 1-100 取出一个数字,小于等于30==中奖
//获取从1 - 100的一个随机数
let n = rand(1, 100);
//判断
if(n <= 30){
alert('恭喜恭喜, 奖品为 10万 RMB 劳斯莱斯优惠券');
}else{
alert('再接再厉');
}
}, 0);
})
script>
body>
html>
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>Documenttitle>
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;
}
/**
点击按钮后显示是否中奖(30%概率中奖)
若中奖弹出 恭喜恭喜, 奖品为 10万 RMB 劳斯莱斯优惠券
若未中奖弹出 再接再厉
*/
//获取元素对象
const btn = document.querySelector('#btn');
//绑定单击事件
btn.addEventListener('click', function(){
//Promise 形式实现
// Promise 构造函数接收的参数为一个函数(函数的参数为两个函数)
// resolve 解决 函数类型的数据
// reject 拒绝 函数类型的数据
// 1) 创建 promise 对象(pending 状态), 指定执行器函数
const p = new Promise((resolve, reject)=>{
// 2) 在执行器函数中启动异步任务
setTimeout(() => {
let n = rand(1, 100);
//判断
// 3) 根据结果做不同处理
if(n <= 30){
// 如果成功了, 调用 resolve(), 指定成功的 value, 变为 resolved 状态
resolve(n); // 将 promise 对象的状态设置为 『成功』调用 resolve 函数
}else{
// 如果失败了, 调用 reject(), 指定失败的 reason, 变为 rejected 状态
reject(n); // 将 promise 对象的状态设置为 『失败』调用 reject 函数
}
}, 0);
})
//调用 then 方法
// 指定成功和失败要执行的函数
// 状态为成功,调用第一个函数,状态为失败,执行第二个函数
// 成功失败函数的参数
// value 值 成功函数参数
// reason 理由 失败函数参数
p.then((value) => {
alert('恭喜恭喜, 奖品为 10万 RMB 劳斯莱斯优惠券, 您的中奖数字为 ' + value);
}, (reason) => {
alert('再接再厉, 您的号码为 ' + reason);
});
})
script>
body>
html>
// 导入 fs 模块
const fs = require('fs');
// 回调函数的方式读取文件
fs.readFile( './content.txt', (err, data)=>{
if ( err ) throw err // 出错抛出错误
console.log( data.toString() ) //输出内容
} )
// 导入 fs 模块
const fs = require('fs')
// 基于promise读取文件
const p = new Promise( (resolve, reject)=>{
fs.readFile( './content.txt', (err, data)=>{
if ( err ) reject( err )
else resolve( data )
} )
} )
// 调用then处理读取文件的结果
p.then( value=>{
console.log( value.toString() )
}, reason=>{
console.log(reason)
} )
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Promise 封装 AJAXtitle>
head>
<body>
<div class="container">
<h2 class="page-header">Promise 封装 AJAX 操作h2>
<button class="btn btn-primary" id="btn">点击发送 AJAXbutton>
div>
<script>
// 接口地址 https://api.liulongbin 跨域了
// https://www.escook.cn/api/get 跨域了
// 获取按钮
const btn = document.querySelector('#btn')
btn.addEventListener( 'click', ()=>{
// 创建 Promise 对象
const p = new Promise( (resolve, reject)=>{
// 创建请求对象
const xhr = new XMLHttpRequest()
// 初始化
xhr.open( 'GET', 'https://www.escook.cn/api/get' ) // 跨域了
// 设置请求头
// xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
// 发送请求
xhr.send()
// 处理响应的结果
xhr.onreadystatechange = ()=>{
if ( xhr.readyState===4 ) {
// 成功
if ( xhr.status>=200 && xhr.status<300 ) {
// 请求响应信息 xhr.response
resolve( xhr.response )
} else {
// xhr.status 请求状态
reject( xhr.status )
}
}
}
} )
p.then( value=>{
console.log( value )
}, reason=>{
console.log( reason )
} )
} )
script>
body>
/**
* 封装一个函数 mineReadFile 读取文件内容
* 参数: path 文件路径
* 返回: promise 对象
*/
// 导入 fs
const fs = require( 'fs' )
const mineReadFile = ( path )=>{
return new Promise( (resolve, reject)=>{
fs.readFile( path, ( err, data )=>{
if(err) reject(err)
resolve(data)
} )
} )
}
// 调用读取文件的方法
// 指定对应的成功和失败的处理函数
mineReadFile( './content.txt' )
.then( val=>{
// 输出文件的内容
console.log( val.toString() )
}, reason=>{
// 输出错误信息
console.log( reason )
} )
/**
* util.promisify 方法
*/
// 引入 util 模块
const util = require( 'util' )
// 引入 fs 模块
const fs = require( 'fs' )
// 使用 util.promisify 方法封装 fs.readFile
// 参数为一个函数
const mineReadFile = util.promisify( fs.readFile )
// 调用函数,并且指定对应的成功和失败处理函数
mineReadFile( './content.txt' ).then( val=>{
console.log( val.toString() )
}, reason=>{
console.log( reason )
} )
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>Documenttitle>
head>
<body>
<script>
/**
* 封装一个函数 sendAJAX 发送 GET AJAX 请求
* 参数 URL
* 返回结果 Promise 对象
*/
function sendAJAX( url ) {
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>
实例对象中的一个属性 『PromiseState』
promise 的状态改变
说明:
只有这 2 种(只能pending 变为 resolved / fullfilled 或 pending 变为 rejected,没有其他的状态变化), 且一个 promise 对象只能改变一次,无论变为成功还是失败, 都会有一个结果数据,成功的结果数据一般称为 value, 失败的结果数据一般称为 reason。
promise: 启动异步任务 => 返回promie对象 => 给promise对象绑定回调函数(甚至可以在异步任务结束后指定/多个) => 根据函数中执行成功或失败的结果,改变promise的状态 => 调用对应的成功或失败的函数。
Promise (excutor)
executor 会在 Promise 内部立即同步调用,异步操作在执行器中执行,执行构造函数时会立即执行 executor 函数。
// 成功
// 创建Promise实例对象时同步执行传入的执行器函数
const p1 = new Promise( (resolve, reject)=>{
console.log( 'executor 执行' )
if(true) {
resolve()
} else {
reject()
}
} )
console.log( p1 )
// 失败
const p2 = new Promise( (resolve, reject)=>{
console.log( 'executor 执行' )
if(false) {
resolve()
} else {
reject()
}
} )
console.log( p2 )
Promise.prototype.then 方法: (onResolved, onRejected) => {}
指定用于得到成功 value 的成功回调和用于得到失败 reason 的失败回调返回一个新的 promise 对象
// 成功
const p1 = new Promise( (resolve, reject)=>{
resolve('ok')
} )
// 执行第一个函数 -- 成功的回调函数
p1.then( val=>{
console.log(val)
}, reason=>{
console.log(reason)
} )
// 失败
const p2 = new Promise( (resolve, reject)=>{
reject('Error')
} )
// 执行第二个函数 -- 失败的回调函数
p2.then( val=>{
console.log(val)
}, reason=>{
console.log(reason)
} )
Promise.prototype.catch 方法: (onRejected) => {}
then()的语法糖, 相当于: then(undefined, onRejected)
catch 定义用于处理失败的回调函数,不定义成功的回调函数
const p = new Promise( (resolve, reject)=>{
reject('error')
} )
// Promise的状态为失败时才调用catch中的回调函数
p.catch( reason=>{
console.log(reason)
} )
const pp = new Promise( (resolve, reject)=>{
resolve('ok')
} )
// Promise的状态为失败时才调用catch中的回调函数
pp.catch( reason=>{
console.log(reason)
} )
Promise.resolve 方法: (value) => {}
返回一个成功/失败的 promise 对象
// 如果传入的参数为 非Promise类型的对象, 则返回的结果为成功promise对象
const p1 = Promise.resolve( 123 )
console.log(p1)
// 如果传入的参数为 Promise 对象, 则参数的结果决定了 resolve 的结果
const p2 = Promise.resolve( new Promise( (resolve, reject)=>{
resolve('ok')
} ) )
console.log(p2);
const p3 = Promise.resolve( new Promise( (resolve, reject)=>{
reject('error')
} ) )
console.log(p3);
Promise.reject 方法: (reason) => {}
返回一个失败的 promise 对象
const p1 = Promise.reject( new Promise((resolve, reject)=>{
resolve('ok')
}) )
console.log(p1)
Promise.all 方法: (promises) => {}
返回一个新的 promise, 只有所有的 promise 都成功才成功, 只要有一个失败了就直接失败
const p1 = Promise.resolve('OK')
const p2 = Promise.reject('Error')
// 处理失败,防止报错
p2.catch( reason=>{} )
const p3 = new Promise( (resolve, reject)=>{
resolve('ok')
} )
// p1 p3 的状态为成功,p2 为失败,res1的状态为失败
const res1 = Promise.all( [p1, p2, p3] )
// 处理失败,防止报错
res1.catch( reason=>{} )
// p1 p3 的状态为成功,res2的状态为成功
const res2 = Promise.all( [p1, p3] )
console.log( res1 )
console.log( res2 )
Promise.race 方法: (promises) => {}
返回一个新的 promise, 第一个完成的 promise 的结果状态就是最终的结果状态
const p1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('ok')
}, 1000)
})
const p2 = Promise.resolve('ok')
const p3 = Promise.reject('err')
const res = Promise.race([p1, p2, p3])
console.log(res)
let p = new Promise( (resolve, reject)=>{
resolve('ok')
} )
// resolve -- 成功
console.log(p)
p = new Promise( (resolve, reject)=>{
reject('ok')
} )
// reject -- 失败
console.log(p)
p = new Promise( (resolve, reject)=>{
throw 'err'
} )
// 抛出错误为失败
console.log(p)
一个 promise 指定多个成功/失败回调函数, 都会调用吗?
let p = new Promise((resolve, reject) => {
resolve('OK');
})
// 状态为成功,后面的成功的回调函数都会被调用
p.then( val=>{
console.log('成功的回调函数')
} )
p.then( val=>{
console.log('成功的回调函数')
} )
p.then( val=>{
console.log('成功的回调函数')
} )
// 先指定回调函数
// 再改变状态
// 执行器中的执行的为异步任务,调用回调函数在1秒后
let p = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('OK')
}, 1000)
})
p.then(
(value) => {
console.log(value)
},
(reason) => {}
)
// 先改变状态
// 执行器内为同步任务
// 执行执行器就立马调用成功的回调函数
// 先改变状态在指定回调函数
p = new Promise((resolve, reject) => {
resolve('OK')
})
p.then(
(value) => {
console.log(value)
},
(reason) => {}
)
promise.then()返回的新 promise 的结果状态由什么决定?
// 1
let p = new Promise((resolve, reject) => {
resolve('ok')
})
let res = p.then(
(val) => {
throw 'err'
},
(reason) => {}
)
console.log(res)
// 2
p = new Promise((resolve, reject) => {
resolve('ok')
})
res = p.then(
(val) => {
return 123
},
(reason) => {}
)
console.log(res)
// 3
p = new Promise((resolve, reject) => {
resolve('ok')
})
res = p.then(
(val) => {
return new Promise.reject('Err')
},
(reason) => {}
)
console.log(res)
let p = new Promise((resolve, reject) => {
resolve('ok')
})
p.then((val) => {
return new Promise((resolve, reject) => {
resolve('OK')
})
})
.then((val) => {
console.log(val)
})
.then((val) => {
// 上一个then结果集中没有返回值,结果集为undefined
// 输出为undefined
console.log(val)
})
let p = new Promise((resolve, reject) => {
resolve('ok')
})
p.then( val=>{
throw 'err'
} ).then( val=>{
console.log(222);
} ).then( val=>{
console.log(222);
} ).catch( reason=>{
console.log(reason)
} )
出错之后直接到catch,中的其他then不执行
let p = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('OK');
}, 1000);
});
p.then(value => {
console.log(111);
//有且只有一个方式
// 新创建的Promise对象,且没有调用回调函数,或抛出错误
// 对象的状态没有改变
// 所以该Promise对象的状态为pending
// 下面的then,catch定义的为失败或成功的回调函数
// 所以会中断退出,不会继续向下执行
return new Promise(() => {});
}).then(value => {
console.log(222);
}).then(value => {
console.log(333);
}).catch(reason => {
console.warn(reason);
});
// 定义Promise的构造函数
function Promise(excutor) {
}
// 定义Promise的then函数
// 定义在prototype上
Promise.prototype.then = function () {
}
官方的 Promise 的实例化对象的 then 等函数都在其原型链上,所以自定义的 Promise 的 then 等函数也挂在原型链上。
// 定义Promise的构造函数
function Promise(excutor) {
// 在执行构造函数时会同步立即执行执行器函数
// 调用传参传过来的执行器函数
// 执行器函数中有两个参数,resolve函数与reject函数
// 执行执行器函数需要传入两个参数,resolve函数与reject函数
excutor(resolve, reject)
}
// 定义Promise的构造函数
function Promise(excutor) {
// 执行器函数执行过程中会调用resolve或reject函数改变Promise的状态
// resolve与reject函数需要定义
// 定义resolve函数
// 会传递过来一个参数,用于改变Promise的结果值 PromiseResult
function resolve(data) {
}
// 定义reject函数
// 会传递过来一个参数,用于改变Promise的结果值 PromiseResult
function reject(data) {
}
// 调用传参传过来的执行器函数
excutor(resolve, reject)
}
// 定义Promise的构造函数
function Promise(excutor) {
// resolve函数与reject函数改变 Promise的状态 PromiseState 和 Promise的结果 PromiseResult
// PromiseState PromiseResult 每个 Promise 对象都有,所以定义在构造函数中
this.PromiseState = 'pending' // 默认状态 pending
this.PromiseResult = null // 结果默认为空
// 定义resolve函数
function resolve(data) {
// 修改 Promise的状态 PromiseState 为成功 fulfilled/resolved
this.PromiseState = 'fulfilled'
// 修改 Promise的结果 PromiseResult 为 data
this.PromiseResult = data
}
// 定义reject函数
function reject(data) {
// 修改 Promise的状态 PromiseState 为成功 rejected
this.PromiseState = 'rejected'
// 修改 Promise的结果 PromiseResult 为 data
this.PromiseResult = data
}
// 调用传参传过来的执行器函数 同步调用
excutor(resolve, reject)
}
// 定义Promise的构造函数
function Promise(excutor) {
// 定义 PromiseState PromiseResult
this.PromiseState = 'pending' // 默认状态 pending
this.PromiseResult = null // 结果默认为空
// 定义resolve函数
function resolve(data) {
this.PromiseState = 'fulfilled' // 修改 Promise的状态 PromiseState
this.PromiseResult = data // 修改 Promise的结果 PromiseResult
}
// 定义reject函数
function reject(data) {
this.PromiseState = 'rejected' // 修改 Promise的状态 PromiseState
this.PromiseResult = data // 修改 Promise的结果 PromiseResult
}
// 异常在 excutor 中抛出的
// 捕获 excutor 中的异常并进行处理
try {
// 调用传参传过来的执行器函数 同步调用
excutor(resolve, reject)
} catch(e) {
// 处理异常
// 改变Promise状态为失败,改变结果
// 直接调用 reject 函数 传入失败信息
reject(e)
}
}
Promise 的状态只能修改一次,只能从 pending 到成功或从 pending 到失败,没有其他可能的改变
// 定义Promise的构造函数
function Promise(excutor) {
// 定义 PromiseState PromiseResult
this.PromiseState = 'pending' // 默认状态 pending
this.PromiseResult = null // 结果默认为空
// 定义resolve函数
function resolve(data) {
// 状态只能修改一次
// 如果状态已经修改了(即不为pending)就直接退出
if (this.PromiseState !== 'pending') return;
this.PromiseState = 'fulfilled' // 修改 Promise的状态 PromiseState
this.PromiseResult = data // 修改 Promise的结果 PromiseResult
}
// 定义reject函数
function reject(data) {
// 状态只能修改一次
// 如果状态已经修改了(即不为pending)就直接退出
if (this.PromiseState !== 'pending') return;
this.PromiseState = 'rejected' // 修改 Promise的状态 PromiseState
this.PromiseResult = data // 修改 Promise的结果 PromiseResult
}
// 捕获 excutor 中的异常并进行处理
try {
// 调用传参传过来的执行器函数 同步调用
excutor(resolve, reject)
} catch (e) {
// 处理异常,改变Promise状态为失败,改变结果
reject(e)
}
}
// 成功状态测试
let p1 = new Promise( (resolve, reject)=>{
resolve('OK')
} )
// p.then(val=>{
// console.log(val)
// }, reason=>{
// console.log(reason)
// })
console.log(p1)
// 失败状态测试
let p2 = new Promise( (resolve, reject)=>{
reject('error')
} )
console.log(p2)
// 抛出异常测试
let p3 = new Promise( (resolve, reject)=>{
throw 'Error'
} )
console.log(p3)
会发现Promise的状态和结果没有进行更改
造成的原因:创建Promise对象时,传入的执行器函数为箭头函数,箭头函数没有自己的this,箭头函数的this会指向外层的this。
<body>
<script>
let p1 = new Promise( (resolve, reject)=>{
resolve('OK')
} )
script>
body>
箭头函数的外层为页面,外层的this指向window,所以箭头函数的this指向window,因此需要想办法让传入执行器为箭头函数this指向Promise对象
// 定义Promise的构造函数
function Promise(excutor) {
// 定义 PromiseState PromiseResult
this.PromiseState = 'pending' // 默认状态 pending
this.PromiseResult = null // 结果默认为空
// 在构造 Promise 对象时将 Promise 对象的 this 保存下来
// 修改时修改 self 上的属性即可,self 指向本对象的this
// self 就是本对象
const self = this
// 定义resolve函数
function resolve(data) {
if (self.PromiseState !== 'pending') return // 状态已经修改直接退出
self.PromiseState = 'fulfilled' // 修改 Promise的状态 PromiseState
self.PromiseResult = data // 修改 Promise的结果 PromiseResult
}
// 定义reject函数
function reject(data) {
if (self.PromiseState !== 'pending') return // 状态已经修改直接退出
self.PromiseState = 'rejected' // 修改 Promise的状态 PromiseState
self.PromiseResult = data // 修改 Promise的结果 PromiseResult
}
// 捕获 excutor 中的异常并进行处理
try {
// 调用传参传过来的执行器函数 同步调用
excutor(resolve, reject)
} catch (e) {
// 处理异常,改变Promise状态为失败,改变结果
reject(e)
}
}
<body>
<script>
// 成功状态测试
let p1 = new Promise( (resolve, reject)=>{
resolve('OK')
} )
// p.then(val=>{
// console.log(val)
// }, reason=>{
// console.log(reason)
// })
console.log(p1)
// 失败状态测试
let p2 = new Promise( (resolve, reject)=>{
reject('error')
} )
console.log(p2)
// 抛出异常测试
let p3 = new Promise( (resolve, reject)=>{
throw 'Error'
} )
console.log(p3)
script>
body>
// 定义 Promise 的 then 方法
// 定义在 prototype 上
// then 方法中有两个函数类型的参数 成功状态的回调函数和失败状态的回调函数
Promise.prototype.then = function (onResolved, onRejected) {
// 根据 Promise 的状态 PromiseState 判断要调用哪个回调函数
// 状态为成功
if (this.PromiseState === 'fulfilled' || this.PromiseState === 'resolved') {
onResolved( this.PromiseResult )
}
// 状态为失败
if (this.PromiseState === 'rejected') {
onRejected( this.PromiseResult )
}
}
then 方法不为箭头函数,为普通函数,有自己的this,指向调用该方法的实例对象
测试:
<body>
<script>
// 成功状态测试
console.log('===== 成功状态测试 =====')
let p1 = new Promise( (resolve, reject)=>{
resolve('OK')
} )
p1.then(val=>{
console.log(val)
}, reason=>{
console.log(reason)
})
console.log(p1)
// 失败状态测试
console.log('===== 失败状态测试 =====')
let p2 = new Promise( (resolve, reject)=>{
reject('error')
} )
p2.then(val=>{
console.log(val)
}, reason=>{
console.log(reason)
})
console.log(p2)
// 抛出异常测试
console.log('===== 抛出异常测试 =====')
let p3 = new Promise( (resolve, reject)=>{
throw 'Error'
} )
p3.then(val=>{
console.log(val)
}, reason=>{
console.log(reason)
})
console.log(p3)
script>
body>
执行器函数中改为异步任务,会发现没有任何输出
let p1 = new Promise( (resolve, reject)=>{
setTimeout(()=>{
resolve('OK')
}, 500)
} )
p1.then(val=>{
console.log(val)
}, reason=>{
console.log(reason)
})
原因:
所以 then() 中的回调函数并未执行,不会有任何的输出。then() 中缺少对于pending状态时候的判断,需要增加对于pending状态的判断。
// 定义 Promise 的 then 方法
// 定义在 prototype 上
// then 方法中有两个函数类型的参数 成功状态的回调函数和失败状态的回调函数
Promise.prototype.then = function (onResolved, onRejected) {
// 根据 Promise 的状态 PromiseState 判断要调用哪个回调函数
// 状态为成功
if (this.PromiseState === 'fulfilled' || this.PromiseState === 'resolved') {
onResolved(this.PromiseResult)
console.log(this)
}
// 状态为失败
if (this.PromiseState === 'rejected') {
onRejected(this.PromiseResult)
console.log(this)
}
// 状态为 pending
if (this.PromiseState === 'pending') {
// then() 中回调函数执行的时机为 Promise 状态改变之后
// 所以回调函数应该在状态改变之后进行调用
// 因此回调函数在resolve或reject函数中转台改变之后进行调用
// 但是resolve和reject与then为不同的函数,不同的函数作用域
// 需要将回调函数进行保存后才可以在resolve或reject中进行调用
// 在构造函数中声明一个对象来保存回调函数
// 在then()使用其来保存回调函数
this.callback = {
onResolved: onResolved,
onRejected: onRejected
}
// 简写
// this.callback = {
// onResolved,
// onRejected
// }
}
}
// 在构造函数中声明一个回调函数对象用于保存回调函数,
// 以便在resolve或reject中执行
this.callback = {}
// 定义Promise的构造函数
function Promise(excutor) {
// 定义 PromiseState PromiseResult
this.PromiseState = 'pending' // 默认状态 pending
this.PromiseResult = null // 结果默认为空
const self = this // 将 Promise 对象的 this 保存下来
// 在构造函数中声明一个回调函数对象用于保存回调函数,
// 以便在resolve或reject中执行
this.callback = {}
// 定义resolve函数
function resolve(data) {
if (self.PromiseState !== 'pending') return // 状态已经修改直接退出
self.PromiseState = 'fulfilled' // 修改 Promise的状态 PromiseState
self.PromiseResult = data // 修改 Promise的结果 PromiseResult
// 状态改变之后有成功的回调函数,调用成功的回调函数
if (self.callback.onResolved) {
self.callback.onResolved(self.PromiseResult);
}
}
// 定义reject函数
function reject(data) {
if (self.PromiseState !== 'pending') return // 状态已经修改直接退出
self.PromiseState = 'rejected' // 修改 Promise的状态 PromiseState
self.PromiseResult = data // 修改 Promise的结果 PromiseResult
// 状态改变之后有失败的回调函数,调用失败的回调函数
if (self.callback.onResolved) {
self.callback.onResolved(self.PromiseResult);
}
}
// 捕获 excutor 中的异常并进行处理
try {
// 调用传参传过来的执行器函数 同步调用
excutor(resolve, reject)
} catch (e) {
// 处理异常,改变Promise状态为失败,改变结果
reject(e)
}
}
测试:
let p1 = new Promise( (resolve, reject)=>{
setTimeout(()=>{
resolve('OK')
}, 500)
} )
p1.then(val=>{
console.log(val)
}, reason=>{
console.log(reason)
})
let p2 = new Promise( (resolve, reject)=>{
setTimeout(()=>{
reject('err')
}, 500)
} )
p2.then(val=>{
console.log(val)
}, reason=>{
console.log(reason)
})
给p1多指定一个回调函数,会发现只有最后指定的回调函数被执行(原因:后面指定的回调函数覆盖了前面的回调函数)
let p1 = new Promise( (resolve, reject)=>{
setTimeout(()=>{
resolve('OK')
}, 500)
} )
p1.then(val=>{
console.log(val)
}, reason=>{
console.log(reason)
})
p1.then(val=>{
console.log(val+'!!!!!!!')
}, reason=>{
console.log(reason+'!!!!!!!')
})
要执行多个回调函数,那么就需要将每个回调函数进行保存,因此改用数组保存回调函数。
this.callback = [] // 声明一个数组用于保存回调函数
// 状态为 pending
if (this.PromiseState === 'pending') {
this.callback.push({
onResolved: onResolved,
onRejected: onRejected
})
}
// 定义resolve函数
function resolve(data) {
if (self.PromiseState !== 'pending') return // 状态已经修改直接退出
self.PromiseState = 'fulfilled' // 修改 Promise的状态 PromiseState
self.PromiseResult = data // 修改 Promise的结果 PromiseResult
self.callback.forEach(item=>{ // 调用所有的回调函数
item.onResolved(self.PromiseResult)
});
}
// 定义reject函数
function reject(data) {
if (self.PromiseState !== 'pending') return // 状态已经修改直接退出
self.PromiseState = 'rejected' // 修改 Promise的状态 PromiseState
self.PromiseResult = data // 修改 Promise的结果 PromiseResult
self.callback.forEach(item=>{ // 调用所有的回调函数
item.onRejected(self.PromiseResult)
});
}
完整代码:
// 定义Promise的构造函数
function Promise(excutor) {
// 定义 PromiseState PromiseResult
this.PromiseState = 'pending' // 默认状态 pending
this.PromiseResult = null // 结果默认为空
const self = this // 将 Promise 对象的 this 保存下来
this.callback = [] // 声明一个数组用于保存回调函数
// 定义resolve函数
function resolve(data) {
if (self.PromiseState !== 'pending') return // 状态已经修改直接退出
self.PromiseState = 'fulfilled' // 修改 Promise的状态 PromiseState
self.PromiseResult = data // 修改 Promise的结果 PromiseResult
self.callback.forEach(item=>{ // 调用所有的回调函数
item.onResolved(self.PromiseResult)
});
}
// 定义reject函数
function reject(data) {
if (self.PromiseState !== 'pending') return // 状态已经修改直接退出
self.PromiseState = 'rejected' // 修改 Promise的状态 PromiseState
self.PromiseResult = data // 修改 Promise的结果 PromiseResult
self.callback.forEach(item=>{ // 调用所有的回调函数
item.onRejected(self.PromiseResult)
});
}
// 捕获 excutor 中的异常并进行处理
try {
// 调用传参传过来的执行器函数 同步调用
excutor(resolve, reject)
} catch (e) {
// 处理异常,改变Promise状态为失败,改变结果
reject(e)
}
}
// 定义 Promise 的 then 方法
// 定义在 prototype 上
// then 方法中有两个函数类型的参数 成功状态的回调函数和失败状态的回调函数
Promise.prototype.then = function (onResolved, onRejected) {
// 根据 Promise 的状态 PromiseState 判断要调用哪个回调函数
// 状态为成功
if (this.PromiseState === 'fulfilled' || this.PromiseState === 'resolved') {
onResolved(this.PromiseResult)
console.log(this)
}
// 状态为失败
if (this.PromiseState === 'rejected') {
onRejected(this.PromiseResult)
console.log(this)
}
// 状态为 pending
if (this.PromiseState === 'pending') {
this.callback.push({
onResolved: onResolved,
onRejected: onRejected
})
}
}
测试:
let p1 = new Promise( (resolve, reject)=>{
setTimeout(()=>{
resolve('OK')
}, 500)
} )
p1.then(val=>{
console.log(val)
}, reason=>{
console.log(reason)
})
p1.then(val=>{
console.log(val+'!!!!!!!')
}, reason=>{
console.log(reason+'!!!!!!!')
})
let p2 = new Promise( (resolve, reject)=>{
setTimeout(()=>{
reject('err')
}, 500)
} )
p2.then(val=>{
console.log(val)
}, reason=>{
console.log(reason)
})
官方的then()执行完回调函数后会返回一个Promise对象,但是目前自己实现的Promise在执行完回调函数后不会返回一个Promise对象
let p2 = new Promise( (resolve, reject)=>{
reject('err')
} )
const res2 = p2.then(val=>{
console.log(val)
}, reason=>{
console.log(reason)
})
console.log(res2)
回调函数执行后没有Promise对象返回
then()返回Promise对象的状态,执行成功的回调函数为成功,执行失败的回调函数为失败,return一个Promise对象根据return的Promise对象状态进行判断。
以回调函数为失败的回调函数为例:
// 状态为失败
if (this.PromiseState === 'rejected') {
// 获取回调函数执行的结果
const result = onRejected(this.PromiseResult)
if (result instanceof Promise) { // 如果是Promise的实例对象
// 返回的为Promise实例对象,指定了then,那么result状态改变肯定会执行then中回调函数
result.then(v => {
resolve(v) // 调用成功函数,改变返回的Promise对象为成功
}, r => {
reject(r) // 调用失败函数,改变返回的Promise对象为失败
})
} else {
// 执行的为失败的对调函数,返回的Promise一定为失败
// 调用返回Promise对象的reject函数改变返回Promise对象的状态和结果
resolve(result)
}
}
测试:
let p2 = new Promise( (resolve, reject)=>{
reject('err')
} )
const res2 = p2.then(val=>{
console.log(val)
}, reason=>{
console.log(reason)
})
console.log(res2)
回调函数的成功的写法一样:
// 定义 Promise 的 then 方法
Promise.prototype.then = function (onResolved, onRejected) {
// 执行完then()返回一个Promise对象
return new Promise((resolve, reject) => {
// 状态为成功
if (this.PromiseState === 'fulfilled' || this.PromiseState === 'resolved') {
const result = onResolved(this.PromiseResult)
if (result instanceof Promise) { // 如果是Promise的实例对象
// 返回的为Promise实例对象,指定了then,那么result状态改变肯定会执行then中回调函数
result.then(v => {
resolve(v) // 调用成功函数,改变返回的Promise对象为成功
}, r => {
reject(r) // 调用失败函数,改变返回的Promise对象为失败
})
} else {
// 执行的为失败的对调函数,返回的Promise一定为失败
// 调用返回Promise对象的reject函数改变返回Promise对象的状态和结果
resolve(result)
}
}
// 状态为失败
if (this.PromiseState === 'rejected') {
// 获取回调函数执行的结果
const result = onRejected(this.PromiseResult)
if (result instanceof Promise) { // 如果是Promise的实例对象
// 返回的为Promise实例对象,指定了then,那么result状态改变肯定会执行then中回调函数
result.then(v => {
resolve(v) // 调用成功函数,改变返回的Promise对象为成功
}, r => {
reject(r) // 调用失败函数,改变返回的Promise对象为失败
})
} else {
// 执行的为失败的对调函数,返回的Promise一定为失败
// 调用返回Promise对象的reject函数改变返回Promise对象的状态和结果
reject(result)
}
}
// 状态为 pending
if (this.PromiseState === 'pending') {
this.callback.push({
onResolved: onResolved,
onRejected: onRejected
})
}
})
}
测试:
let p1 = new Promise( (resolve, reject)=>{
resolve('OK')
} )
const res1 = p1.then(val=>{
console.log(val)
}, reason=>{
console.log(reason)
})
console.log(res1)
let p2 = new Promise( (resolve, reject)=>{
reject('err')
} )
const res2 = p2.then(val=>{
console.log(val)
}, reason=>{
console.log(reason)
})
console.log(res2)
抛出错误处理:
// 状态为失败
if (this.PromiseState === 'rejected') {
try {
// 获取回调函数执行的结果
const result = onRejected(this.PromiseResult)
if (result instanceof Promise) { // 如果是Promise的实例对象
// 返回的为Promise实例对象,指定了then,那么result状态改变肯定会执行then中回调函数
result.then(v => {
resolve(v) // 调用成功函数,改变返回的Promise对象为成功
}, r => {
reject(r) // 调用失败函数,改变返回的Promise对象为失败
})
} else {
// 执行的为失败的对调函数,返回的Promise一定为失败
// 调用返回Promise对象的reject函数改变返回Promise对象的状态和结果
reject(result)
}
} catch (e) {
// 抛出错误状态就为失败
reject(e)
}
}
测试:
let p1 = new Promise( (resolve, reject)=>{
resolve('OK')
} )
const res1 = p1.then(val=>{
console.log(val)
throw 'error'
}, reason=>{
console.log(reason)
})
console.log(res1)
let p2 = new Promise( (resolve, reject)=>{
reject('err')
} )
const res2 = p2.then(val=>{
console.log(val)
}, reason=>{
console.log(reason)
throw 'error'
})
console.log(res2)
异步任务下then()不会返回有状态的Promise的对象
let p1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('OK')
}, 1000)
})
const res1 = p1.then(
(val) => {
console.log(val)
},
(reason) => {
console.log(reason)
}
)
console.log(res1)
因为回调函数最终执行是在调用then方法对象中的resolve或reject函数中执行
所以对保存的回调函数进行修改,让其调用将要返回的Promise对象的resolve函数或reject函数。
需要对调用then的Promise对象进行保存
// 定义 Promise 的 then 方法
Promise.prototype.then = function (onResolved, onRejected) {
const self = this // 保存调用then的Promise对象
......
}
在保存的函数中调用成功或失败的回调函数,并且执行返回的Promise对象的状态和结果的修改
// 状态为 pending
if (this.PromiseState === 'pending') {
this.callback.push({
onResolved: function () {
// 执行成功的回调函数
// 根据回调函数的结果进行判断,来修改返回对象的状态
const result = onResolved(self.PromiseResult)
// 判断
if (result instanceof Promise) { // 如果是Promise的实例对象
result.then(v => {
resolve(v) // 调用成功函数,改变返回的Promise对象为成功
}, r => {
reject(r) // 调用失败函数,改变返回的Promise对象为失败
})
} else {
resolve(result)
}
},
onRejected: function () {
// 执行失败的回调函数
const result = onResolved(self.PromiseResult)
// 判断
if (result instanceof Promise) { // 如果是Promise的实例对象
result.then(v => {
resolve(v) // 调用成功函数,改变返回的Promise对象为成功
}, r => {
reject(r) // 调用失败函数,改变返回的Promise对象为失败
})
} else {
resolve(result)
}
}
})
}
测试:
let p1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('OK')
}, 1000)
})
const res1 = p1.then(
(val) => {
console.log(val)
},
(reason) => {
console.log(reason)
}
)
console.log(res1)
let p2 = new Promise((resolve, reject) => {
setTimeout(() => {
reject('OK')
}, 1000)
})
const res2 = p2.then(
(val) => {
console.log(val)
},
(reason) => {
console.log(reason)
}
)
console.log(res2)
抛出错误返回的Promise对象
// 状态为 pending
if (this.PromiseState === 'pending') {
this.callback.push({
onResolved: function () {
try {
// 执行成功的回调函数
// 根据回调函数的结果进行判断,来修改返回对象的状态
const result = onResolved(self.PromiseResult)
// 判断
if (result instanceof Promise) { // 如果是Promise的实例对象
result.then(v => {
resolve(v) // 调用成功函数,改变返回的Promise对象为成功
}, r => {
reject(r) // 调用失败函数,改变返回的Promise对象为失败
})
} else {
resolve(result)
}
} catch (e) {
reject(e)
}
},
onRejected: function () {
try {
// 执行失败的回调函数
const result = onResolved(self.PromiseResult)
// 判断
if (result instanceof Promise) { // 如果是Promise的实例对象
result.then(v => {
resolve(v) // 调用成功函数,改变返回的Promise对象为成功
}, r => {
reject(r) // 调用失败函数,改变返回的Promise对象为失败
})
} else {
resolve(result)
}
} catch (e) {
reject(e)
}
}
测试:
let p1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('OK')
}, 1000)
})
const res1 = p1.then(
(val) => {
console.log(val)
throw 'ERROR'
},
(reason) => {
console.log(reason)
}
)
console.log(res1)
会发现三个if中的代码类似,就回调函数有所不同,可以写到外面封装为函数,利于后期维护
注意this的指向
// 定义 Promise 的 then 方法
Promise.prototype.then = function (onResolved, onRejected) {
const self = this // 保存调用then的Promise对象
// 执行完then()返回一个Promise对象
return new Promise((resolve, reject) => {
// 封装函数
function callback(type) {
try {
// 使用this,this指向的不为调用then的Promise对象
const result = type(self.PromiseResult)
if (result instanceof Promise) { // 如果是Promise的实例对象
result.then(v => {
resolve(v) // 调用成功函数,改变返回的Promise对象为成功
}, r => {
reject(r) // 调用失败函数,改变返回的Promise对象为失败
})
} else {
resolve(result)
}
} catch (e) {
reject(e)
}
}
// 状态为成功
if (this.PromiseState === 'fulfilled' || this.PromiseState === 'resolved') {
callback(onResolved)
}
// 状态为失败
if (this.PromiseState === 'rejected') {
callback(onRejected)
}
// 状态为 pending
if (this.PromiseState === 'pending') {
this.callback.push({
onResolved: function () {
callback(onResolved)
},
onRejected: function () {
callback(onRejected)
}
})
}
})
}
// 定义 Promise 的 catch 方法
Promise.prototype.catch = function (onRejected) {
// catch 方法中执行的是失败的回调函数
// 与 then 差别为只有失败的回调函数,可以直接使用then
return this.then( undefined, onRejected )
}
let p1 = new Promise((resolve, reject) => {
setTimeout(() => {
reject('Error')
}, 1000)
})
const res1 = p1.catch(reason=>{
console.log(reason)
})
console.log(res1)
在then的链式调用的过程中不需要对失败的结果进行处理,主要在最后加一个catch方法处理失败的结果即可。
未实现异常穿透测试:
let p1 = new Promise((resolve, reject) => {
setTimeout(() => {
reject('Error')
}, 1000)
})
p1.then((v) => {
console.log(111)
})
.then((v) => {
console.log(222)
})
.catch((r) => {
console.log(r)
})
// 定义 Promise 的 then 方法
Promise.prototype.then = function (onResolved, onRejected) {
const self = this // 保存调用then的Promise对象
// 判断失败的回调函数
// 由于报错造成的原因是失败的回调函数为undefined
// 所以当失败的回调函数为未定义时候,补充一个失败回调
// 让其报错
if (typeof onRejected !== 'function' ) {
onRejected = reason => {
throw reason
}
}
......
}
let p1 = new Promise((resolve, reject) => {
setTimeout(() => {
// reject('Error')
resolve('OK')
}, 1000)
})
p1.then((v) => {
console.log(111)
throw 'ERROR'
})
.then((v) => {
console.log(222)
})
.catch((r) => {
console.log(r)
})
官方的then()在不指定成功的回调函数也可以继续向下执行
let p1 = new Promise((resolve, reject) => {
setTimeout(() => {
// reject('Error')
resolve('OK')
}, 1000)
})
p1.then()
.then((v) => {
console.log(222)
})
.then((v) => {
console.log(333)
})
.catch((r) => {
console.log(r)
})
实现方法,与异常穿透类似,在没有成功的回调函数的时候一样指定一个成功的回调函数
// 定义 Promise 的 then 方法
Promise.prototype.then = function (onResolved, onRejected) {
const self = this // 保存调用then的Promise对象
......
// 没有传递成功的回调函数
// 给一个默认的成功回调函数
if (typeof onResolved !== 'function') {
onResolved = value => {
return value //将resolve中传递的值,即Promise的结果向后传递
}
}
......
}
测试:
let p1 = new Promise((resolve, reject) => {
setTimeout(() => {
// reject('Error')
resolve('OK')
}, 1000)
})
p1.then()
.then((v) => {
console.log(222)
})
.then((v) => {
console.log(333)
})
.catch((r) => {
console.log(r)
})
// 传递的为Promise对象,则返回的Promise的状态由传入的决定
// 传入的为其他值,则返回的Promise对象为成功
Promise.resolve(value) {
return new Promise((resolve, reject) => {
if (value instanceof Promise) {
// 为Promise对象,肯定可以调用then
value.then(v => {
resolve(v)
}, r => {
reject(r)
})
} else {
resolve(value)
}
})
}
测试:
const p1 = Promise.resolve('OK')
const p2 = Promise.resolve(
new Promise((resolve, reject) => {
resolve('OK~~~')
})
)
const p3 = Promise.resolve(
new Promise((resolve, reject) => {
reject('err')
})
)
console.log(p1)
console.log(p2)
console.log(p3)
无论传递什么值都返回一个失败的Promise对象
Promise.reject = function(value) {
return new Promise((resolve, reject) => {
reject(value)
})
}
测试:
const p1 = Promise.reject('OK')
const p2 = Promise.reject(
new Promise((resolve, reject) => {
resolve('OK~~~')
})
)
const p3 = Promise.reject(
new Promise((resolve, reject) => {
reject('err')
})
)
console.log(p1)
console.log(p2)
console.log(p3)
Promise对象数组中所有的都为成功返回的Promise对象才成功,有一个失败返回的就为失败。
Promise.all = function (promises) {
// 返回一个Promise对象
return new Promise((resolve, reject) => {
// 记录状态为成功的promise对象个数
let count = 0;
// 保存成功promise对象的结果
let arr = []
for (let i = 0; i < promises.length; i++) {
// Promise 对象肯定可以调用 then
promises[i].then(v => {
// 状态为成功的个数++
count++
// 保证数组中结果集的顺序与传入的promise对象的顺序一样
arr[i] = v
// 状态为成功的个数与promise对象数组的个数一样
if (count === promises.length) {
resolve(arr)
}
}, r => {
reject(r)
})
}
})
}
测试:
const p1 = Promise.resolve('OK')
const p2 = Promise.resolve(
new Promise((resolve, reject) => {
resolve('OK~~~')
})
)
const p3 = Promise.reject(
new Promise((resolve, reject) => {
reject('err')
})
)
const res1 = Promise.all([p1, p2])
const res2 = Promise.all([p1, p2, p3])
console.log(res1)
console.log(res2)
最先改变状态的promise对象的状态为返回的Promise对象的状态,其结果为返回的Promise对象的结果。
Promise.race = function (promises) {
return new Promise((resolve, reject) => {
for (let i = 0; i < promises.length; i++) {
// 第一个改变状态的promise在其回调函数直接改变返回promise的回调函数
promises[i].then(v => {
resolve(v)
}, r => {
reject(r)
})
}
})
}
const p1 = Promise.resolve(
new Promise((resolve, reject) => {
setTimeout(()=>{
resolve('OK~~~')
}, 1000)
})
)
const p2 = Promise.resolve('OK')
const p3 = Promise.reject(
new Promise((resolve, reject) => {
reject('err')
})
)
const res1 = Promise.race([p1, p2, p3])
console.log(res1)
官方的then
const p1 = new Promise((resolve, reject) => {
resolve('OK')
console.log(111)
})
p1.then((v) => {
console.log(222)
})
console.log(333)
我们的then
修改方法:(原先的回调函数均为同步执行的)将其修改为异步任务
// 状态为成功
if (this.PromiseState === 'fulfilled' || this.PromiseState === 'resolved') {
setTimeout(() => {
callback(onResolved)
});
}
// 状态为失败
if (this.PromiseState === 'rejected') {
setTimeout(() => {
callback(onRejected)
});
}
// 定义resolve函数
function resolve(data) {
if (self.PromiseState !== 'pending') return // 状态已经修改直接退出
self.PromiseState = 'fulfilled' // 修改 Promise的状态 PromiseState
self.PromiseResult = data // 修改 Promise的结果 PromiseResult
setTimeout(() => {
self.callback.forEach(item => { // 调用所有的回调函数
item.onResolved(self.PromiseResult)
})
})
}
// 定义reject函数
function reject(data) {
if (self.PromiseState !== 'pending') return // 状态已经修改直接退出
self.PromiseState = 'rejected' // 修改 Promise的状态 PromiseState
self.PromiseResult = data // 修改 Promise的结果 PromiseResult
setTimeout(() => {
self.callback.forEach(item => { // 调用所有的回调函数
item.onRejected(self.PromiseResult)
})
})
}
class Promise {
constructor(excutor) {
// 定义 PromiseState PromiseResult
this.PromiseState = 'pending' // 默认状态 pending
this.PromiseResult = null // 结果默认为空
const self = this // 将 Promise 对象的 this 保存下来
this.callback = [] // 声明一个数组用于保存回调函数
// 定义resolve函数
function resolve(data) {
if (self.PromiseState !== 'pending') return // 状态已经修改直接退出
self.PromiseState = 'fulfilled' // 修改 Promise的状态 PromiseState
self.PromiseResult = data // 修改 Promise的结果 PromiseResult
setTimeout(() => {
self.callback.forEach(item => { // 调用所有的回调函数
item.onResolved(self.PromiseResult)
})
})
}
// 定义reject函数
function reject(data) {
if (self.PromiseState !== 'pending') return // 状态已经修改直接退出
self.PromiseState = 'rejected' // 修改 Promise的状态 PromiseState
self.PromiseResult = data // 修改 Promise的结果 PromiseResult
setTimeout(() => {
self.callback.forEach(item => { // 调用所有的回调函数
item.onRejected(self.PromiseResult)
})
})
}
// 捕获 excutor 中的异常并进行处理
try {
// 调用传参传过来的执行器函数 同步调用
excutor(resolve, reject)
} catch (e) {
// 处理异常,改变Promise状态为失败,改变结果
reject(e)
}
}
then(onResolved, onRejected) {
const self = this // 保存调用then的Promise对象
// 判断失败的回调函数
// 由于报错造成的原因是失败的回调函数为undefined
// 所以当失败的回调函数为未定义时候,补充一个失败回调
// 让其报错
if (typeof onRejected !== 'function') {
onRejected = reason => {
throw reason
}
}
// 没有传递成功的回调函数
// 给一个默认的成功回调函数
if (typeof onResolved !== 'function') {
onResolved = value => {
return value //将resolve中传递的值,即Promise的结果向后传递
}
}
// 执行完then()返回一个Promise对象
return new Promise((resolve, reject) => {
// 封装函数
function callback(type) {
try {
const result = type(self.PromiseResult)
if (result instanceof Promise) { // 如果是Promise的实例对象
result.then(v => {
resolve(v) // 调用成功函数,改变返回的Promise对象为成功
}, r => {
reject(r) // 调用失败函数,改变返回的Promise对象为失败
})
} else {
resolve(result)
}
} catch (e) {
reject(e)
}
}
// 状态为成功
if (this.PromiseState === 'fulfilled' || this.PromiseState === 'resolved') {
setTimeout(() => {
callback(onResolved)
});
}
// 状态为失败
if (this.PromiseState === 'rejected') {
setTimeout(() => {
callback(onRejected)
});
}
// 状态为 pending
if (this.PromiseState === 'pending') {
this.callback.push({
onResolved: function () {
callback(onResolved)
},
onRejected: function () {
callback(onRejected)
}
})
}
})
}
catch(onRejected) {
// catch 方法中执行的是失败的回调函数
// 与 then 差别为只有失败的回调函数,可以直接使用then
return this.then(undefined, onRejected)
}
// resolve、reject、all、race不属于实例对象,属于类
// 用static进行修饰
static resolve(value) {
return new Promise((resolve, reject) => {
if (value instanceof Promise) {
// 为Promise对象,肯定可以调用then
value.then(v => {
resolve(v)
}, r => {
reject(r)
})
} else {
resolve(value)
}
})
}
static reject(value) {
return new Promise((resolve, reject) => {
reject(value)
})
}
static all(promises) {
// 返回一个Promise对象
return new Promise((resolve, reject) => {
// 记录状态为成功的promise对象个数
let count = 0;
// 保存成功promise对象的结果
let arr = []
for (let i = 0; i < promises.length; i++) {
// Promise 对象肯定可以调用 then
promises[i].then(v => {
// 状态为成功的个数++
count++
// 保证数组中结果集的顺序与传入的promise对象的顺序一样
arr[i] = v
// 状态为成功的个数与promise对象数组的个数一样
if (count === promises.length) {
resolve(arr)
}
}, r => {
reject(r)
})
}
})
}
static race(promises) {
return new Promise((resolve, reject) => {
for (let i = 0; i < promises.length; i++) {
// 第一个改变状态的promise在其回调函数直接改变返回promise的回调函数
promises[i].then(v => {
resolve(v)
}, r => {
reject(r)
})
}
})
}
}
测试:
const p1 = new Promise((resolve, reject) => {
resolve('OK')
console.log(111)
})
p1.then((v) => {
console.log(222)
})
console.log(333)
【async】
【await】
async函数的返回值为 promise 对象
async function f1() {
}
const res1 = f1()
console.log(res1)
promise 对象的结果由 async 函数执行的返回值决定(与then的规则一样)
返回的为非Promise对象的数据,则函数返回的结果为成功的Promise对象,Promise对象的结果为return的结果
async function f1() {
return 123
}
const res1 = f1()
console.log(res1)
返回的为失败的Promise,函数返回的为失败的Promise
async function f1() {
return new Promise((resolve, reject)=>{
reject('OK')
})
}
const res1 = f1()
console.log(res1)
返回的为成功的Promise,函数返回的为成功的Promise
async function f1() {
return new Promise((resolve, reject)=>{
resolve('OK')
})
}
const res1 = f1()
console.log(res1)
函数抛出错误,返回的为失败的Promise
async function f1() {
throw 'ERROR'
}
const res1 = f1()
console.log(res1)
await 右侧的表达式一般为 promise 对象, 但也可以是其它的值,运算相关的也行
如果表达式是 promise 对象, await 返回的是 promise 成功的值
async function f() {
const p = Promise.resolve('OK')
let res = await p
console.log(res)
}
f()
如果表达式是其它值, 直接将此值作为 await 的返回值
async function f() {
let res = await 20
console.log(res)
}
f()
注意
await 必须写在 async 函数中, 但 async 函数中可以没有 await
await 20;
如果 await 的 promise 失败了, 就会抛出异常, 需要通过 try…catch 捕获处理
async function f() {
const p = Promise.reject('ERROR')
let res = await p
console.log(res)
}
f()
async function f() {
const p = Promise.reject('ERROR')
try {
let res = await p
} catch (error) {
console.log(error)
}
}
f()
const { log } = require('console')
const fs = require('fs')
// 会出现data变量名覆盖
fs.readFile('./content.txt', (err, data1) => {
if (err) return err
fs.readFile('./content.txt', (err, data2) => {
if (err) return err
fs.readFile('./content.txt', (err, data3) => {
if (err) return err
log( data1+data2+data3 )
} )
})
})
const { log } = require('console')
const fs = require('fs')
// util 中的 util.promisify() 可以对读取文件的方法进行封装
const util = require('util')
const myReadFile = util.promisify(fs.readFile)
// 读取文件
async function read() {
let data1 = await myReadFile('./content.txt')
let data2 = await myReadFile('./content.txt')
let data3 = await myReadFile('./content.txt')
log(data1 + data2 + data3)
}
read()
使用async与await,也便于报错处理,不像fs回调那样每层都要独立的报错处理
const { log } = require('console')
const fs = require('fs')
// util 中的 util.promisify() 可以对读取文件的方法进行封装
const util = require('util')
const myReadFile = util.promisify(fs.readFile)
// 读取文件
async function read() {
try {
let data1 = await myReadFile('./content1111111111111.txt')
let data2 = await myReadFile('./content.txt')
let data3 = await myReadFile('./content.txt')
log(data1 + data2 + data3)
} catch (e) {
log(e)
}
}
read()