Promise函数的基本了解
----------简单来说,promise函数是为了解决异步回调时的一些问题,更准确来说是为了解决我们在开发中,经常会面临的“回调地狱”所给开发者带来的困扰。promise可以被理解成一个方案,来有助于我们快速规避这些麻烦,从而提高我们的开发效率。
----------我们知道一个Promise函数的状态必然处于以下几种状态中的一个:
- 待定(pending) :初始状态,既没有被兑现,也没有被拒绝。
- 已兑现(fulfilled) :意味着操作成功完成。
- 已拒绝(rejected) :意味着操作失败。
为什么要使用Promise
----指定回调函数的方式更加灵活
旧的:必须在启动异步任务前指定
promise:启动异步任务=》返回promise对象=》给promise对象绑定回调函数(甚至可以在异步任务)
----支持链式调用,可以解决回调地狱问题
那什么是回调地狱---》回调函数调用,外部回调函数异步执行的结果是嵌套的回调执行的条件,其缺点不方便阅读,不便于异常处理,解决方案是promise链式调用。
promise内置的几种方法
既然我们知道了promise的作用之后,我们就来谈谈promise函数所内置的几个API,也就是方法,这些方法在我们往后的学习和工作当中会被反复的使用,因此要熟悉这些API能实现的功能变的尤为重要:
-
resolve:promise构造函数上挂载或在内部定义的方法,表示一个“成功”时的状态,且此状态一旦生成就不可逆,此过程也称为“敲定”了这个状态。
-
reject:promise构造函数上挂载或在内部定义的方法,表示一个“失败”时的状态,且此状态一旦生成就不可逆,此过程也称为“敲定”了这个状态。
-
then:promise.then方法返回的结果也是一个promise函数,准确来说是一个对象,这个对象中有then方法返回的promise对象及其所处的状态和结果值等,因此这个新对象也可以使用promise所内置的方法。
-
catch:catch在promise中经常用来快速捕捉异常,例如捕捉throw抛错时而导致的非正常状态,在自定义封装中我们用try ...catch来搭配使用,catch返回值是一个失败的promise对象。
-
all: promise中all方法的参数接受一个数组,这个数组的成员要满足都为promise对象。如果所有的promise对象状态都为“fulfilled”,也就是成功,all方法返回一个状态也为成功的promise对象,此对象内部的结果值为此成功的数组。若有一个promise成员的状态为失败,那么all方法就会返回一个失败的promise对象,其状态为"rejected",其内部结果值为这个数组中失败的promise函数的结果值。
-
race: promise中race方法的参数接受一个数组,这个数组的成员要满足都为promise对象,race方法返回一个promise对-象,这个对象的状态由数组中第一个状态改变的promise函数决定,且两个对象的状态保持一致,且其结果值为数组中第一个状态改变的promise函数的结果值。
Promise对象状态改变的三种方式
- resolve('ok');//状态改变pending---->fulfilled(resolved)
- reject ('error');//状态改变pending---->rejected
- throw '抛出错误了'//抛出错误
Promise.then()返回的新的promise的结果状态由什么决定?
简单表述:由then()指定的回调函数执行的结果决定
----Promise.reject
该方法将始终返回一个为失败的Promise对象,无论参数是否为Promise类型还是其他,最终都是放回失败的Promise。
----Promise下的resolve方法
作用:将一个普通的值转化为Promise类型的数据,
分两种情况:
1.当resolve方法参数为非Promise对象,则返回的结果为成功的Promise对象
2.当resolve方法参数为Promise对象,则参数对象的状态和结果将直接影响最终resolve方法的
返回值的那个对象的状态和结果
--------finally
是ES9中新增的特性,表示无论Promise对象变成了fulfilled还是rejected状态,最终都会执行finally方法的回调函数参数是不接受参数的
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>promise.all</title>
<style></style>
<script src="./promise.js"></script>
</head>
<body>
<script>
// 欢迎来到 我的世界-
// 基本格式
let p = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('执行value')
console.log(1);
}, 100)
console.log(2);
})
p.then(value=>{
console.log(3);
},reason=>{
console.log(4);
})
console.log(5);
</script>
</body>
</html>
js代码
// 定义promise构造函数
function Promise(executor) {
// 设置默认状态和默认值
this.PromiseState = 'pending'
this.PromiseResult = null
// 设置一个空数组,异步时调用
this.callbacks = []
// this赋给self
const self = this
// 成功时的函数
function resolve(data) {
// 判断此时的p的状态是否已经改变
if (self.PromiseState !== 'pending') return
// 设置实例成功时的状态和结果值
self.PromiseState = 'fulfilled'
self.PromiseResult = data
// 执行调用函数为resolve的异步任务
self.callbacks.forEach(item => {
item.onResolved(data)
})
}
// 失败时的函数
function reject(data) {
// 判断此时的p的状态是否已经改变
if (self.PromiseState !== 'pending') return
// 设置实例成功时的状态和结果值
self.PromiseState = 'rejected'
self.PromiseResult = data
// 执行调用函数为reject的异步任务
self.callbacks.forEach(item => {
item.onRejected(data)
})
}
// 执行函数并捕捉可能存在的异常
try {
executor(resolve, reject)
} catch (e) {
reject(e)
}
}
// 在promise函数原型上挂载一个then方法
Promise.prototype.then = function (onResolved, onRejected) {
const self = this
// 若用户没有传入onResolved箭头函数
if (typeof onResolved !== 'function') {
onResolved = value => value
}
// 若用户没有传入onRejected箭头函数
if (typeof onRejected !== 'function') {
onRejected = resaon => {
throw resaon
}
}
return new Promise((resolve, reject) => {
// 封装common函数
function common(type) {
try {
// 执行函数,并且把执行结果赋值给result变量
let result = type(self.PromiseResult)
if (result instanceof Promise) {
result.then(v => {
resolve(v)
}, r => {
reject(r)
})
} else {
resolve(result)
}
} catch (e) {
reject(e)
}
}
// 成功时的then
if (this.PromiseState === 'fulfilled') {
setTimeout(() => {
common(onResolved)
})
}
// 失败时的then
if (this.PromiseState === 'rejected') {
setTimeout(() => {
common(onRejected);
})
}
// 异步执行的then
if (this.PromiseState === 'pending') {
self.callbacks.push(
{
onResolved: function (data) {
common(onResolved)
},
onRejected: function (data) {
common(onRejected)
}
}
)
}
})
}
// 给构造函数Promise挂载resolve函数
Promise.resolve = function (data) {
return new Promise((resolve, reject) => {
if (data instanceof Promise) {
data.then(v => {
resolve(v)
}, r => {
reject(r)
})
} else {
resolve(data)
}
})
}
// 给构造函数Promise挂载reject函数
Promise.reject = function (data) {
return new Promise((resolve, reject) => {
reject(data)
})
}
// 挂载catch方法
Promise.prototype.catch = function (onRejected) {
return this.then(undefined, onRejected)
}
// 挂载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 => {
count++;
arr[i] = v
if (count === promises.length) {
resolve(arr)
}
}, r => {
reject(r)
})
}
})
}
// 挂载race方法
Promise.race = function (promises) {
for (let i = 0; i < promises.length; i++) {
return new Promise((resolve, reject) => {
promises[i].then(v => {
resolve(v)
}, r => {
reject(r)
})
})
}
}
代码优化的步骤:
- 实现异步任务的成功执行
- promise构造函数优化
- then方法返回值优化
- 完善then方法的内部代码
- 封装common函数,提高代码的可读性
- 在promise构造函数上挂载一个resolve和reject方法
为promise构造函数挂载catch方法
为promise构造函数挂载all方法
为promise构造函数挂载race方法
异步打印的相关优化