一、Promise的使用
在学习如何写Promise之前,先要熟悉Promise的使用,然后一步一步去实现
【Promise的基本使用】:
Promise 是一个类 在执行这个类的时候需要传递一个执行器进去,执行器会立即执行
Promise中有三种状态,分别是:等待pending 成功fulfilled 失败rejected(状态一旦确定不可改变)
执行器接收两个参数resolve(成功执行的方法)和reject(失败执行的方法)
Promise拥有then方法,方法内部需判断状态,接收了两个回调函数,如果成功调用成功的回调,如果失败调用失败的回调。then方法是被定义在原型对象中的
const promise = new Promise((resolve, reject) => {
resolve('成功')
// reject('失败')
})
promise.then(value => {
console.log(value)
}, reason => {
console.log(reason)
})
二、手写Promise
【实现步骤】:
- 创建MyPromise类
- 通过构造函数constructor,在执行这个类的时候需要传递一个执行器进去并立即调用
- 定义resolve和reject(定义为箭头函数:避免直接调用时this指向全局window问题)
- 定义状态常量(成功fulfilled 失败rejected 等待pending),初始化为pending。
- 完成resolve和reject函数的状态改变(注意:需判断当前状态是否可以改变)
- MyPromise类中定义value和reason,用来储存执行器执行成功和失败的返回值
- MyPromise类中添加then方法,成功回调有一个参数 表示成功之后的值;失败回调有一个参数 表示失败后的原因
- 处理异步逻辑(pending状态下在then中将回调存起来)
- 实现then方法多次调用添加多个处理函数
- 实现then方法链式调用(写一个函数方法专门判断回调的结果是普通值还是promise,then方法返回的仍然是一个promise)
- 处理promise返回值各种类型情况(普通值,promise)
- then方法链式调用识别Promise对象自返回
- Promise实现捕获错误及then链式调用其他状态代码补充
- 将then方法的参数变为可选参数
- Promise.all
- Promise.resolve 返回一个promise
- finally方法 不管成功失败都会执行一次
- catch方法的实现
【代码】:
// 4. 定义状态常量(成功fulfilled 失败rejected 等待pending),初始化为pending。
const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'
// 1 创建MyPromise类
class MyPromise {
// 2 通过构造函数constructor,在执行这个类的时候需要传递一个执行器进去并立即调用
constructor(executor) {
// 13 Promise实现捕获错误
try {
executor(this.resolve, this.reject)
} catch (e) {
this.reject(e)
}
}
status = PENDING
// 6. MyPromise类中定义value和reason,用来储存执行器执行成功和失败的返回值
value = null
reason = null
// 9. 实现then方法多次调用添加多个处理函数 初始化回调为数组依次执行
successCallback = []
failCallback = []
// 3. 定义resolve和reject(定义为箭头函数:避免直接调用时this指向全局window问题)
resolve = value => {
// 5. 完成resolve函数的状态改变(注意:需判断当前状态是否可以改变)
// 判断当前状态是否可改变
if(this.status !== PENDING) return
// 改变当前状态
this.status = FULFILLED
// 保存返回值
this.value = value
// 执行成功回调
while(this.successCallback.length) {
this.successCallback.shift()(this.value)
}
}
reject = reason => {
// 5. 完成reject函数的状态改变(注意:需判断当前状态是否可以改变)
// 判断当前状态是否可改变
if(this.status !== PENDING) return
// 改变当前状态
this.status = REJECTED
// 保存返回值
this.reason = reason
// 执行失败回调
while(this.failCallback.length) {
this.failCallback.shift()(this.reason)
}
}
// 7. MyPromise类中添加then方法,成功回调有一个参数 表示成功之后的值;失败回调有一个参数 表示失败后的原因
then(successCallback, failCallback) {
// 14 将then方法的参数变为可选参数
successCallback = successCallback ? successCallback : value => this.value
failCallback = failCallback ? failCallback : reason => {throw this.reason}
// 10. 实现then方法链式调用(写一个函数方法专门判断回调的结果是普通值还是promise,then方法返回的仍然是一个promise)
let promise2 = new MyPromise((resolve, reject) => {
// 判断当前状态 执行对应回调 异步情况下存储当前回调等待执行
if(this.status === FULFILLED) {
// 异步
setTimeout(() => {
// 13 then方法捕获错误
try {
// 异步获取到promise2
let x = successCallback(this.value)
resolvePromise(promise2, x, resolve, reject)
} catch (e) {
reject(e)
}
})
} else if(this.status === REJECTED) {
// 异步
setTimeout(() => {
// 13 then方法捕获错误
try {
// 异步获取到promise2
let x = failCallback(this.reason)
resolvePromise(promise2, x, resolve, reject)
} catch (e) {
reject(e)
}
})
} else {
// 8. 处理异步逻辑(pending状态下在then中将回调存起来)
this.successCallback.push(() => {
try {
let x = successCallback(this.value)
resolvePromise(promise2, x, resolve, reject)
} catch(e) {
reject(e)
}
})
this.failCallback.push(() => {
try {
let x = failCallback(this.reason)
resolvePromise(promise2, x, resolve, reject)
} catch(e) {
reject(e)
}
})
}
})
return promise2
}
// 17. finally方法 不管成功失败都会执行一次
finally(callback) {
return this.then(value => {
return MyPromise.resolve(callback()).then(() => value)
}, reason => {
return MyPromise.reject(callback()).then(() => { throw reason })
})
}
// 18. catch
catch(failCallback) {
return this.then(undefined, failCallback)
}
// 15. Promise.all
static all (array) {
let result = []
let index
return new Promise((resolve, reject) => {
function addData(key, value) {
result[key] = value
index++
if(index === array.length) {
resolve(result)
}
}
for(let i = 0; i < array.length; i++) {
let current = array[i]
if(current instanceof MyPromise) {
current.then(value => addData(i, value), reason => reject(reason))
} else {
addData(i, array[i])
}
}
})
}
// 16. Promise.resolve 返回一个promise
static resolve(value) {
if(value instanceof MyPromise) return value
return new MyPromise(resolve => resolve(value))
}
}
// 处理promise返回值各种类型情况(普通值,promise)
function resolvePromise(promise2, x, resolve, reject) {
if(promise2 === x) {
return reject(new TypeError('Chaining cycle detected for promise #<Promise>'))
}
if(x instanceof MyPromise) {
x.then(resolve, reject)
} else {
resolve(x)
}
}
【对应验证代码】:
<!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>Document</title>
</head>
<body>
<script src="./promise2.js"></script>
<!-- <script src="./newPromise.js"></script> -->
<script>
// 1、基础
let promise = new MyPromise((resolve, reject) => {
resolve('成功')
// reject('失败')
})
promise.then(value=>{
console.log(value)
},reason=>{
console.log(reason)
})
// 2、异步
let promise = new Promise((resolve, reject) => {
setTimeout(() => { // 异步
resolve('成功')
}, 2000)
// reject('失败')
})
promise.then(value=>{
console.log(value)
},reason=>{
console.log(reason)
})
// 3、then方法链式调用
let promise = new MyPromise((resolve, reject) => {
setTimeout(() => { // 异步
resolve('成功')
}, 2000)
// reject('失败')
})
function other () {
return new MyPromise((resolve, reject) => {
resolve('other')
})
}
promise.then(value=>{
console.log(value)
return other()
}).then(value => {
console.log(value)
})
// 4、promise对象子返回循环报错
var promise = new Promise(function(resolve, reject) {
resolve(100)
})
var p1 = promise.then(function(value) {
return p1
})
p1.then(value => {
console.log(value)
}, reason => {
console.log(reason.message)
})
// 5、Promise实现捕获错误及then链式调用其他状态代码补充
var promise = new MyPromise(function(resolve, reject) {
// setTimeout(() => {
// resolve('成功。。。')
// },2000)
throw new Error('executor error')
// resolve('成功')
})
promise.then(value => {
console.log(value)
// throw new Error('then error')
return 'aaa'
}, reason => {
console.log('报错')
console.log(reason)
return '123'
}).then(value => {
console.log('value2')
console.log(value)
}, reason => {
console.log('报错2')
console.log(reason)
})
// 6、将then方法的参数变为可选参数
var promise = new MyPromise(function(resolve, reject) {
resolve(100)
})
promise.then().then(value => value).then(value => console.log(value))
// 7、Promise.all
// 按照异步代码调用顺序得到结果
// 类直接调用的方法是静态方法
function p1() {
return new Promise(function (resolve, reject) {
setTimeout(function() {
resolve('p1')
},2000)
})
}
function p2() {
return new Promise(function (resolve, reject) {
resolve('p2')
})
}
Promise.all(['a', 'b', p1(), p2(), 'c']).then(function(result) {
// result -> ['a', 'b', 'p1', 'p2', 'c']
console.log(result)
})
// 8、Promise.resolve将给定的值转换为promise对象
function p1() {
return new Promise(function (resolve, reject) {
resolve('hello')
})
}
Promise.resolve(10).then(value => console.log(value))
Promise.resolve(p1()).then(value => console.log(value))
// 9、finally方法无论promise执行成功或失败finally都会执行一次
// finally方法后可链式调用then方法拿到最终返回的结果
function p1() {
return new Promise(function (resolve, reject) {
reject('hello')
})
}
p1().finally(() => {
console.log('finally')
}).then(value => {
console.log(value)
}, reason => {
console.log('error')
console.log(reason)
})
// 10、catch
function p1() {
return new Promise(function (resolve, reject) {
resolve('hello')
})
}
p1()
.then(value => {
return a
})
.then(value => console.log('value2:' + value))
.catch(reason => console.log('catch:' + reason))
</script>
</body>
</html>
版权归原作者 齐旗 所有, 如有侵权,请联系我们删除。